merge master in master_gl
diff --git a/api/current.xml b/api/current.xml
index 3174f09..8b5f7ed 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -683,6 +683,17 @@
  visibility="public"
 >
 </field>
+<field name="READ_HISTORY_BOOKMARKS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.permission.READ_HISTORY_BOOKMARKS&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="READ_INPUT_STATE"
  type="java.lang.String"
  transient="false"
@@ -1134,6 +1145,17 @@
  visibility="public"
 >
 </field>
+<field name="WRITE_HISTORY_BOOKMARKS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.permission.WRITE_HISTORY_BOOKMARKS&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="WRITE_OWNER_DATA"
  type="java.lang.String"
  transient="false"
@@ -3540,17 +3562,6 @@
  visibility="public"
 >
 </field>
-<field name="donut_resource_pad29"
- type="int"
- transient="false"
- volatile="false"
- value="16843395"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="donut_resource_pad3"
  type="int"
  transient="false"
@@ -3727,6 +3738,17 @@
  visibility="public"
 >
 </field>
+<field name="dropDownHeight"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843395"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="dropDownHintAppearance"
  type="int"
  transient="false"
@@ -26043,6 +26065,17 @@
  visibility="public"
 >
 </field>
+<field name="USER_QUERY"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;user_query&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <interface name="SearchManager.OnCancelListener"
  abstract="true"
@@ -29227,6 +29260,21 @@
 <parameter name="name" type="java.lang.String">
 </parameter>
 </method>
+<method name="addStatusChangeListener"
+ return="java.lang.Object"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mask" type="int">
+</parameter>
+<parameter name="callback" type="android.content.SyncStatusObserver">
+</parameter>
+</method>
 <method name="applyBatch"
  return="android.content.ContentProviderResult[]"
  abstract="false"
@@ -29268,12 +29316,27 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="uri" type="android.net.Uri">
 </parameter>
 </method>
+<method name="cancelSync"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="account" type="android.accounts.Account">
+</parameter>
+<parameter name="authority" type="java.lang.String">
+</parameter>
+</method>
 <method name="delete"
  return="int"
  abstract="false"
@@ -29291,6 +29354,43 @@
 <parameter name="selectionArgs" type="java.lang.String[]">
 </parameter>
 </method>
+<method name="getMasterSyncAutomatically"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSyncAdapterTypes"
+ return="android.content.SyncAdapterType[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSyncAutomatically"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="account" type="android.accounts.Account">
+</parameter>
+<parameter name="authority" type="java.lang.String">
+</parameter>
+</method>
 <method name="getType"
  return="java.lang.String"
  abstract="false"
@@ -29319,6 +29419,36 @@
 <parameter name="values" type="android.content.ContentValues">
 </parameter>
 </method>
+<method name="isSyncActive"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="account" type="android.accounts.Account">
+</parameter>
+<parameter name="authority" type="java.lang.String">
+</parameter>
+</method>
+<method name="isSyncPending"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="account" type="android.accounts.Account">
+</parameter>
+<parameter name="authority" type="java.lang.String">
+</parameter>
+</method>
 <method name="notifyChange"
  return="void"
  abstract="false"
@@ -29491,6 +29621,66 @@
 <parameter name="observer" type="android.database.ContentObserver">
 </parameter>
 </method>
+<method name="removeStatusChangeListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="handle" type="java.lang.Object">
+</parameter>
+</method>
+<method name="requestSync"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="account" type="android.accounts.Account">
+</parameter>
+<parameter name="authority" type="java.lang.String">
+</parameter>
+<parameter name="extras" type="android.os.Bundle">
+</parameter>
+</method>
+<method name="setMasterSyncAutomatically"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="sync" type="boolean">
+</parameter>
+</method>
+<method name="setSyncAutomatically"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="account" type="android.accounts.Account">
+</parameter>
+<parameter name="authority" type="java.lang.String">
+</parameter>
+<parameter name="sync" type="boolean">
+</parameter>
+</method>
 <method name="startSync"
  return="void"
  abstract="false"
@@ -29498,7 +29688,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="uri" type="android.net.Uri">
@@ -29613,7 +29803,7 @@
  value="&quot;account&quot;"
  static="true"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </field>
@@ -29646,6 +29836,17 @@
  value="&quot;force&quot;"
  static="true"
  final="true"
+ deprecated="deprecated"
+ visibility="public"
+>
+</field>
+<field name="SYNC_EXTRAS_MANUAL"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;force&quot;"
+ static="true"
+ final="true"
  deprecated="not deprecated"
  visibility="public"
 >
@@ -37881,6 +38082,8 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.os.Parcelable">
+</implements>
 <constructor name="SyncAdapterType"
  type="android.content.SyncAdapterType"
  static="false"
@@ -37893,6 +38096,52 @@
 <parameter name="accountType" type="java.lang.String">
 </parameter>
 </constructor>
+<constructor name="SyncAdapterType"
+ type="android.content.SyncAdapterType"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="android.os.Parcel">
+</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="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="accountType"
  type="java.lang.String"
  transient="false"
@@ -37914,6 +38163,27 @@
 >
 </field>
 </class>
+<interface name="SyncStatusObserver"
+ abstract="true"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onStatusChanged"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="which" type="int">
+</parameter>
+</method>
+</interface>
 <class name="UriMatcher"
  extends="java.lang.Object"
  abstract="false"
@@ -50478,6 +50748,17 @@
  visibility="public"
 >
 </method>
+<method name="prepareToDraw"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="recycle"
  return="void"
  abstract="false"
@@ -72988,6 +73269,21 @@
  visibility="public"
 >
 </method>
+<method name="invoke"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="request" type="android.os.Parcel">
+</parameter>
+<parameter name="reply" type="android.os.Parcel">
+</parameter>
+</method>
 <method name="isLooping"
  return="boolean"
  abstract="false"
@@ -73010,6 +73306,17 @@
  visibility="public"
 >
 </method>
+<method name="newRequest"
+ return="android.os.Parcel"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="pause"
  return="void"
  abstract="false"
@@ -75222,6 +75529,721 @@
  visibility="public"
 >
 </field>
+<field name="TONE_CDMA_ABBR_ALERT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="97"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_ABBR_INTERCEPT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="37"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_ABBR_REORDER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="39"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_ALERT_AUTOREDIAL_LITE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="87"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_ALERT_CALL_GUARD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="93"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_ALERT_INCALL_LITE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="91"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_ALERT_NETWORK_LITE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="86"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_ANSWER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="42"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_CALLDROP_LITE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="95"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_CALL_SIGNAL_ISDN_INTERGROUP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="46"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_CALL_SIGNAL_ISDN_NORMAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="45"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_CALL_SIGNAL_ISDN_PAT3"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="48"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_CALL_SIGNAL_ISDN_PAT5"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="50"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_CALL_SIGNAL_ISDN_PAT6"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="51"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_CALL_SIGNAL_ISDN_PAT7"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="52"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_CALL_SIGNAL_ISDN_PING_RING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="49"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_CALL_SIGNAL_ISDN_SP_PRI"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="47"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_CONFIRM"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="41"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_DIAL_TONE_LITE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="34"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_EMERGENCY_RINGBACK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="92"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_HIGH_L"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="53"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_HIGH_PBX_L"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="71"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_HIGH_PBX_SLS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="80"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_HIGH_PBX_SS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="74"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_HIGH_PBX_SSL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="77"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_HIGH_PBX_S_X4"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="83"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_HIGH_SLS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="65"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_HIGH_SS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="56"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_HIGH_SSL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="59"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_HIGH_SS_2"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="62"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_HIGH_S_X4"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="68"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_INTERCEPT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="36"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_KEYPAD_VOLUME_KEY_LITE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="89"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_LOW_L"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="55"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_LOW_PBX_L"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="73"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_LOW_PBX_SLS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="82"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_LOW_PBX_SS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="76"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_LOW_PBX_SSL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="79"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_LOW_PBX_S_X4"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="85"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_LOW_SLS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="67"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_LOW_SS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="58"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_LOW_SSL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="61"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_LOW_SS_2"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="64"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_LOW_S_X4"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="70"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_MED_L"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="54"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_MED_PBX_L"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="72"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_MED_PBX_SLS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="81"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_MED_PBX_SS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="75"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_MED_PBX_SSL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="78"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_MED_PBX_S_X4"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="84"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_MED_SLS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="66"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_MED_SS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="57"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_MED_SSL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="60"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_MED_SS_2"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="63"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_MED_S_X4"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="69"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_NETWORK_BUSY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="40"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_NETWORK_BUSY_ONE_SHOT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="96"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_NETWORK_CALLWAITING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="43"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_NETWORK_USA_RINGBACK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="35"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_ONE_MIN_BEEP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="88"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_PIP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="44"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_PRESSHOLDKEY_LITE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="90"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_REORDER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="38"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_SIGNAL_OFF"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="98"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="TONE_CDMA_SOFT_ERROR_LITE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="94"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="TONE_DTMF_0"
  type="int"
  transient="false"
@@ -116670,7 +117692,7 @@
 >
 <parameter name="uri" type="android.net.Uri">
 </parameter>
-<parameter name="account" type="java.lang.String">
+<parameter name="accountName" type="java.lang.String">
 </parameter>
 <parameter name="authority" type="java.lang.String">
 </parameter>
@@ -165070,6 +166092,17 @@
  visibility="public"
 >
 </method>
+<method name="getDropDownHeight"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getDropDownHorizontalOffset"
  return="int"
  abstract="false"
@@ -165341,6 +166374,19 @@
 <parameter name="id" type="int">
 </parameter>
 </method>
+<method name="setDropDownHeight"
+ 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="setDropDownHorizontalOffset"
  return="void"
  abstract="false"
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index 81639ad..2f4a1c9 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -32,6 +32,7 @@
 #include <media/AudioSystem.h>
 #include "CameraService.h"
 
+#include <cutils/atomic.h>
 #include <cutils/properties.h>
 
 namespace android {
@@ -42,6 +43,7 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <pthread.h>
+#include <signal.h>
 }
 
 // When you enable this, as well as DEBUG_REFS=1 and
@@ -63,6 +65,10 @@
 static int debug_frame_cnt;
 #endif
 
+static int getCallingPid() {
+    return IPCThreadState::self()->getCallingPid();
+}
+
 // ----------------------------------------------------------------------------
 
 void CameraService::instantiate() {
@@ -76,6 +82,7 @@
     BnCameraService()
 {
     LOGI("CameraService started: pid=%d", getpid());
+    mUsers = 0;
 }
 
 CameraService::~CameraService()
@@ -87,7 +94,9 @@
 
 sp<ICamera> CameraService::connect(const sp<ICameraClient>& cameraClient)
 {
-    LOGD("Connect E from ICameraClient %p", cameraClient->asBinder().get());
+    int callingPid = getCallingPid();
+    LOGD("CameraService::connect E (pid %d, client %p)", callingPid,
+            cameraClient->asBinder().get());
 
     Mutex::Autolock lock(mLock);
     sp<Client> client;
@@ -96,36 +105,50 @@
         if (currentClient != 0) {
             sp<ICameraClient> currentCameraClient(currentClient->getCameraClient());
             if (cameraClient->asBinder() == currentCameraClient->asBinder()) {
-                // this is the same client reconnecting...
-                LOGD("Connect X same client (%p) is reconnecting...", cameraClient->asBinder().get());
+                // This is the same client reconnecting...
+                LOGD("CameraService::connect X (pid %d, same client %p) is reconnecting...",
+                    callingPid, cameraClient->asBinder().get());
                 return currentClient;
             } else {
-                // it's another client... reject it
-                LOGD("new client (%p) attempting to connect - rejected", cameraClient->asBinder().get());
+                // It's another client... reject it
+                LOGD("CameraService::connect X (pid %d, new client %p) rejected. "
+                    "(old pid %d, old client %p)",
+                    callingPid, cameraClient->asBinder().get(),
+                    currentClient->mClientPid, currentCameraClient->asBinder().get());
+                if (kill(currentClient->mClientPid, 0) == -1 && errno == ESRCH) {
+                    LOGD("The old client is dead!");
+                }
                 return client;
             }
         } else {
             // can't promote, the previous client has died...
-            LOGD("new client connecting, old reference was dangling...");
+            LOGD("New client (pid %d) connecting, old reference was dangling...",
+                    callingPid);
             mClient.clear();
+            if (mUsers > 0) {
+                LOGD("Still have client, rejected");
+                return client;
+            }
         }
     }
 
     // create a new Client object
-    client = new Client(this, cameraClient, IPCThreadState::self()->getCallingPid());
+    client = new Client(this, cameraClient, callingPid);
     mClient = client;
 #if DEBUG_CLIENT_REFERENCES
     // Enable tracking for this object, and track increments and decrements of
     // the refcount.
     client->trackMe(true, true);
 #endif
-    LOGD("Connect X");
+    LOGD("CameraService::connect X");
     return client;
 }
 
 void CameraService::removeClient(const sp<ICameraClient>& cameraClient)
 {
-    // declar this outside the lock to make absolutely sure the
+    int callingPid = getCallingPid();
+
+    // Declare this outside the lock to make absolutely sure the
     // destructor won't be called with the lock held.
     sp<Client> client;
 
@@ -133,26 +156,42 @@
 
     if (mClient == 0) {
         // This happens when we have already disconnected.
-        LOGV("mClient is null.");
+        LOGD("removeClient (pid %d): already disconnected", callingPid);
         return;
     }
 
-    // Promote mClient. It should never fail because we're called from
-    // a binder call, so someone has to have a strong reference.
+    // Promote mClient. It can fail if we are called from this path:
+    // Client::~Client() -> disconnect() -> removeClient().
     client = mClient.promote();
     if (client == 0) {
-        LOGW("can't get a strong reference on mClient!");
+        LOGD("removeClient (pid %d): no more strong reference", callingPid);
         mClient.clear();
         return;
     }
 
     if (cameraClient->asBinder() != client->getCameraClient()->asBinder()) {
         // ugh! that's not our client!!
-        LOGW("removeClient() called, but mClient doesn't match!");
+        LOGW("removeClient (pid %d): mClient doesn't match!", callingPid);
     } else {
         // okay, good, forget about mClient
         mClient.clear();
     }
+
+    LOGD("removeClient (pid %d) done", callingPid);
+}
+
+// The reason we need this count is a new CameraService::connect() request may
+// come in while the previous Client's destructor has not been run or is still
+// running. If the last strong reference of the previous Client is gone but
+// destructor has not been run, we should not allow the new Client to be created
+// because we need to wait for the previous Client to tear down the hardware
+// first.
+void CameraService::incUsers() {
+    android_atomic_inc(&mUsers);
+}
+
+void CameraService::decUsers() {
+    android_atomic_dec(&mUsers);
 }
 
 static sp<MediaPlayer> newMediaPlayer(const char *file) 
@@ -177,7 +216,8 @@
 CameraService::Client::Client(const sp<CameraService>& cameraService,
         const sp<ICameraClient>& cameraClient, pid_t clientPid)
 {
-    LOGD("Client E constructor");
+    int callingPid = getCallingPid();
+    LOGD("Client::Client E (pid %d)", callingPid);
     mCameraService = cameraService;
     mCameraClient = cameraClient;
     mClientPid = clientPid;
@@ -189,22 +229,28 @@
 
     // Callback is disabled by default
     mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
-    LOGD("Client X constructor");
+    cameraService->incUsers();
+    LOGD("Client::Client X (pid %d)", callingPid);
 }
 
 status_t CameraService::Client::checkPid()
 {
-    if (mClientPid == IPCThreadState::self()->getCallingPid()) return NO_ERROR;
-    LOGW("Attempt to use locked camera (%p) from different process", getCameraClient()->asBinder().get());
+    int callingPid = getCallingPid();
+    if (mClientPid == callingPid) return NO_ERROR;
+    LOGW("Attempt to use locked camera (client %p) from different process "
+        " (old pid %d, new pid %d)",
+        getCameraClient()->asBinder().get(), mClientPid, callingPid);
     return -EBUSY;
 }
 
 status_t CameraService::Client::lock()
 {
+    int callingPid = getCallingPid();
+    LOGD("lock from pid %d (mClientPid %d)", callingPid, mClientPid);
     Mutex::Autolock _l(mLock);
     // lock camera to this client if the the camera is unlocked
     if (mClientPid == 0) {
-        mClientPid = IPCThreadState::self()->getCallingPid();
+        mClientPid = callingPid;
         return NO_ERROR;
     }
     // returns NO_ERROR if the client already owns the camera, -EBUSY otherwise
@@ -213,13 +259,14 @@
 
 status_t CameraService::Client::unlock()
 {
+    int callingPid = getCallingPid();
+    LOGD("unlock from pid %d (mClientPid %d)", callingPid, mClientPid);    
     Mutex::Autolock _l(mLock);
     // allow anyone to use camera
-    LOGD("unlock (%p)", getCameraClient()->asBinder().get());
     status_t result = checkPid();
     if (result == NO_ERROR) {
         mClientPid = 0;
-
+        LOGD("clear mCameraClient (pid %d)", callingPid);
         // we need to remove the reference so that when app goes
         // away, the reference count goes to 0.
         mCameraClient.clear();
@@ -229,15 +276,17 @@
 
 status_t CameraService::Client::connect(const sp<ICameraClient>& client)
 {
+    int callingPid = getCallingPid();
+
     // connect a new process to the camera
-    LOGD("connect (%p)", client->asBinder().get());
+    LOGD("Client::connect E (pid %d, client %p)", callingPid, client->asBinder().get());
 
     // I hate this hack, but things get really ugly when the media recorder
     // service is handing back the camera to the app. The ICameraClient
     // destructor will be called during the same IPC, making it look like
     // the remote client is trying to disconnect. This hack temporarily
     // sets the mClientPid to an invalid pid to prevent the hardware from
-    //  being torn down.
+    // being torn down.
     {
 
         // hold a reference to the old client or we will deadlock if the client is
@@ -246,24 +295,29 @@
         {
             Mutex::Autolock _l(mLock);
             if (mClientPid != 0 && checkPid() != NO_ERROR) {
-                LOGW("Tried to connect to locked camera");
+                LOGW("Tried to connect to locked camera (old pid %d, new pid %d)",
+                        mClientPid, callingPid);
                 return -EBUSY;
             }
             oldClient = mCameraClient;
 
             // did the client actually change?
-            if (client->asBinder() == mCameraClient->asBinder()) return NO_ERROR;
+            if (client->asBinder() == mCameraClient->asBinder()) {
+                LOGD("Connect to the same client");
+                return NO_ERROR;
+            }
 
             mCameraClient = client;
             mClientPid = -1;
             mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
-            LOGD("connect new process (%d) to existing camera client", mClientPid);
+            LOGD("Connect to the new client (pid %d, client %p)",
+                callingPid, mCameraClient->asBinder().get());
         }
 
     }
     // the old client destructor is called when oldClient goes out of scope
     // now we set the new PID to lock the interface again
-    mClientPid = IPCThreadState::self()->getCallingPid();
+    mClientPid = callingPid;
 
     return NO_ERROR;
 }
@@ -280,8 +334,11 @@
 
 CameraService::Client::~Client()
 {
+    int callingPid = getCallingPid();
+
     // tear down client
-    LOGD("Client (%p)  E destructor", getCameraClient()->asBinder().get());
+    LOGD("Client::~Client E (pid %d, client %p)",
+            callingPid, getCameraClient()->asBinder().get());
     if (mSurface != 0 && !mUseOverlay) {
 #if HAVE_ANDROID_OS
         pthread_t thr;
@@ -307,19 +364,21 @@
     }
 
     // make sure we tear down the hardware
-    mClientPid = IPCThreadState::self()->getCallingPid();
+    mClientPid = callingPid;
     disconnect();
-    LOGD("Client X destructor");
+    LOGD("Client::~Client X (pid %d)", mClientPid);
 }
 
 void CameraService::Client::disconnect()
 {
-    LOGD("Client (%p) E disconnect from (%d)",
-            getCameraClient()->asBinder().get(),
-            IPCThreadState::self()->getCallingPid());
+    int callingPid = getCallingPid();
+
+    LOGD("Client::disconnect() E (pid %d client %p)",
+            callingPid, getCameraClient()->asBinder().get());
+
     Mutex::Autolock lock(mLock);
     if (mClientPid <= 0) {
-        LOGD("camera is unlocked, don't tear down hardware");
+        LOGD("camera is unlocked (mClientPid = %d), don't tear down hardware", mClientPid);
         return;
     }
     if (checkPid() != NO_ERROR) {
@@ -327,25 +386,31 @@
         return;
     }
 
+    // Make sure disconnect() is done once and once only, whether it is called
+    // from the user directly, or called by the destructor.
+    if (mHardware == 0) return;
+
     mCameraService->removeClient(mCameraClient);
-    if (mHardware != 0) {
-        LOGD("hardware teardown");
-        // Before destroying mHardware, we must make sure it's in the
-        // idle state.
-        mHardware->stopPreview();
-        // Cancel all picture callbacks.
-        mHardware->cancelPicture(true, true, true);
-        // Release the hardware resources.
-        mHardware->release();
-    }
+
+    LOGD("hardware teardown");
+    // Before destroying mHardware, we must make sure it's in the
+    // idle state.
+    mHardware->stopPreview();
+    // Cancel all picture callbacks.
+    mHardware->cancelPicture(true, true, true);
+    // Release the hardware resources.
+    mHardware->release();
     mHardware.clear();
-    LOGD("Client X disconnect");
+
+    mCameraService->decUsers();
+
+    LOGD("Client::disconnect() X (pid %d)", callingPid);
 }
 
 // pass the buffered ISurface to the camera service
 status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface)
 {
-    LOGD("setPreviewDisplay(%p)", surface.get());
+    LOGD("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid());
     Mutex::Autolock lock(mLock);
     status_t result = checkPid();
     if (result != NO_ERROR) return result;
@@ -365,7 +430,7 @@
 // preview are handled.
 void CameraService::Client::setPreviewCallbackFlag(int callback_flag)
 {
-    LOGV("setPreviewCallbackFlag");
+    LOGV("setPreviewCallbackFlag (pid %d)", getCallingPid());
     Mutex::Autolock lock(mLock);
     if (checkPid() != NO_ERROR) return;
     mPreviewCallbackFlag = callback_flag;
@@ -374,7 +439,9 @@
 // start preview mode, must call setPreviewDisplay first
 status_t CameraService::Client::startCameraMode(camera_mode mode)
 {
-    LOGD("startCameraMode(%d)", mode);
+    int callingPid = getCallingPid();
+
+    LOGD("startCameraMode(%d) (pid %d)", mode, callingPid);
 
     /* we cannot call into mHardware with mLock held because
      * mHardware has callbacks onto us which acquire this lock
@@ -405,7 +472,7 @@
 
 status_t CameraService::Client::startRecordingMode()
 {
-    LOGV("startRecordingMode");
+    LOGD("startRecordingMode (pid %d)", getCallingPid());
 
     status_t ret = UNKNOWN_ERROR;
 
@@ -433,7 +500,7 @@
 
 status_t CameraService::Client::startPreviewMode()
 {
-    LOGV("startPreviewMode");
+    LOGD("startPreviewMode (pid %d)", getCallingPid());
 
     // if preview has been enabled, nothing needs to be done
     if (mHardware->previewEnabled()) {
@@ -500,11 +567,15 @@
 
 status_t CameraService::Client::startPreview()
 {
+    LOGD("startPreview (pid %d)", getCallingPid());
+    
     return startCameraMode(CAMERA_PREVIEW_MODE);
 }
 
 status_t CameraService::Client::startRecording()
 {
+    LOGD("startRecording (pid %d)", getCallingPid());
+
     if (mMediaPlayerBeep.get() != NULL) {
         mMediaPlayerBeep->seekTo(0);
         mMediaPlayerBeep->start();
@@ -515,7 +586,7 @@
 // stop preview mode
 void CameraService::Client::stopPreview()
 {
-    LOGD("stopPreview()");
+    LOGD("stopPreview (pid %d)", getCallingPid());
 
     Mutex::Autolock lock(mLock);
     if (checkPid() != NO_ERROR) return;
@@ -537,7 +608,7 @@
 // stop recording mode
 void CameraService::Client::stopRecording()
 {
-    LOGV("stopRecording()");
+    LOGD("stopRecording (pid %d)", getCallingPid());
 
     Mutex::Autolock lock(mLock);
     if (checkPid() != NO_ERROR) return;
@@ -552,15 +623,13 @@
         mMediaPlayerBeep->start();
     }
     mHardware->stopRecording();
-    LOGV("stopRecording(), hardware stopped OK");
+    LOGD("stopRecording(), hardware stopped OK");
     mPreviewBuffer.clear();
 }
 
 // release a recording frame
 void CameraService::Client::releaseRecordingFrame(const sp<IMemory>& mem)
 {
-    LOGV("releaseRecordingFrame()");
-
     Mutex::Autolock lock(mLock);
     if (checkPid() != NO_ERROR) return;
 
@@ -704,7 +773,7 @@
 // take a picture - image is returned in callback
 status_t CameraService::Client::autoFocus()
 {
-    LOGV("autoFocus");
+    LOGD("autoFocus (pid %d)", getCallingPid());
 
     Mutex::Autolock lock(mLock);
     status_t result = checkPid();
@@ -722,7 +791,7 @@
 // take a picture - image is returned in callback
 status_t CameraService::Client::takePicture()
 {
-    LOGD("takePicture");
+    LOGD("takePicture (pid %d)", getCallingPid());
 
     Mutex::Autolock lock(mLock);
     status_t result = checkPid();
@@ -920,6 +989,7 @@
 
 void CameraService::Client::postShutter()
 {
+    LOGD("postShutter");
     mCameraClient->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
 }
 
@@ -1029,7 +1099,7 @@
     if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
         snprintf(buffer, SIZE, "Permission Denial: "
                 "can't dump CameraService from pid=%d, uid=%d\n",
-                IPCThreadState::self()->getCallingPid(),
+                getCallingPid(),
                 IPCThreadState::self()->getCallingUid());
         result.append(buffer);
         write(fd, result.string(), result.size());
diff --git a/camera/libcameraservice/CameraService.h b/camera/libcameraservice/CameraService.h
index a421fd3..729e539 100644
--- a/camera/libcameraservice/CameraService.h
+++ b/camera/libcameraservice/CameraService.h
@@ -194,6 +194,11 @@
                             CameraService();
     virtual                 ~CameraService();
 
+    // We use a count for number of clients (shoule only be 0 or 1).
+    volatile    int32_t                     mUsers;
+    virtual     void                        incUsers();
+    virtual     void                        decUsers();
+
     mutable     Mutex                       mLock;
                 wp<Client>                  mClient;
 
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 2a4a672..3782136 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -26,10 +26,13 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.view.IWindowManager;
 
+import java.io.File;
+import java.io.FileNotFoundException;
 import java.util.Iterator;
 import java.util.Set;
 
@@ -446,6 +449,8 @@
             return;
         }
         
+        ParcelFileDescriptor fd = null;
+        
         String cmd = nextArg();
         if ("start".equals(cmd)) {
             start = true;
@@ -455,6 +460,16 @@
                 showUsage();
                 return;
             }
+            try {
+                fd = ParcelFileDescriptor.open(
+                        new File(profileFile),
+                        ParcelFileDescriptor.MODE_CREATE |
+                        ParcelFileDescriptor.MODE_TRUNCATE |
+                        ParcelFileDescriptor.MODE_READ_WRITE);
+            } catch (FileNotFoundException e) {
+                System.err.println("Error: Unable to open file: " + profileFile);
+                return;
+            }
         } else if (!"stop".equals(cmd)) {
             System.err.println("Error: Profile command " + cmd + " not valid");
             showUsage();
@@ -462,8 +477,8 @@
         }
         
         try {
-            if (!mAm.profileControl(process, start, profileFile)) {
-                System.out.println("PROFILE FAILED on process " + process);
+            if (!mAm.profileControl(process, start, profileFile, fd)) {
+                System.err.println("PROFILE FAILED on process " + process);
                 return;
             }
         } catch (IllegalArgumentException e) {
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index b6f855a..dfa8139 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -986,7 +986,9 @@
             String process = data.readString();
             boolean start = data.readInt() != 0;
             String path = data.readString();
-            boolean res = profileControl(process, start, path);
+            ParcelFileDescriptor fd = data.readInt() != 0
+                    ? data.readFileDescriptor() : null;
+            boolean res = profileControl(process, start, path, fd);
             reply.writeNoException();
             reply.writeInt(res ? 1 : 0);
             return true;
@@ -2232,7 +2234,7 @@
     }
     
     public boolean profileControl(String process, boolean start,
-            String path) throws RemoteException
+            String path, ParcelFileDescriptor fd) throws RemoteException
     {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
@@ -2240,6 +2242,12 @@
         data.writeString(process);
         data.writeInt(start ? 1 : 0);
         data.writeString(path);
+        if (fd != null) {
+            data.writeInt(1);
+            fd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+        } else {
+            data.writeInt(0);
+        }
         mRemote.transact(PROFILE_CONTROL_TRANSACTION, data, reply, 0);
         reply.readException();
         boolean res = reply.readInt() != 0;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 98bd45a..79588ea 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -48,6 +48,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.MessageQueue;
+import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -74,6 +75,7 @@
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileOutputStream;
+import java.io.IOException;
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
@@ -1236,6 +1238,11 @@
         String who;
     }
 
+    private static final class ProfilerControlData {
+        String path;
+        ParcelFileDescriptor fd;
+    }
+
     private final class ApplicationThread extends ApplicationThreadNative {
         private static final String HEAP_COLUMN = "%17s %8s %8s %8s %8s";
         private static final String ONE_COUNT_COLUMN = "%17s %8d";
@@ -1494,8 +1501,11 @@
             }
         }
         
-        public void profilerControl(boolean start, String path) {
-            queueOrSendMessage(H.PROFILER_CONTROL, path, start ? 1 : 0);
+        public void profilerControl(boolean start, String path, ParcelFileDescriptor fd) {
+            ProfilerControlData pcd = new ProfilerControlData();
+            pcd.path = path;
+            pcd.fd = fd;
+            queueOrSendMessage(H.PROFILER_CONTROL, pcd, start ? 1 : 0);
         }
 
         public void setSchedulingGroup(int group) {
@@ -1838,7 +1848,7 @@
                     handleActivityConfigurationChanged((IBinder)msg.obj);
                     break;
                 case PROFILER_CONTROL:
-                    handleProfilerControl(msg.arg1 != 0, (String)msg.obj);
+                    handleProfilerControl(msg.arg1 != 0, (ProfilerControlData)msg.obj);
                     break;
                 case CREATE_BACKUP_AGENT:
                     handleCreateBackupAgent((CreateBackupAgentData)msg.obj);
@@ -3618,15 +3628,20 @@
         performConfigurationChanged(r.activity, mConfiguration);
     }
 
-    final void handleProfilerControl(boolean start, String path) {
+    final void handleProfilerControl(boolean start, ProfilerControlData pcd) {
         if (start) {
-            File file = new File(path);
-            file.getParentFile().mkdirs();
             try {
-                Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
+                Debug.startMethodTracing(pcd.path, pcd.fd.getFileDescriptor(),
+                        8 * 1024 * 1024, 0);
             } catch (RuntimeException e) {
-                Log.w(TAG, "Profiling failed on path " + path
+                Log.w(TAG, "Profiling failed on path " + pcd.path
                         + " -- can the process access this path?");
+            } finally {
+                try {
+                    pcd.fd.close();
+                } catch (IOException e) {
+                    Log.w(TAG, "Failure closing profile fd", e);
+                }
             }
         } else {
             Debug.stopMethodTracing();
diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java
index 1666588..8ec1445 100644
--- a/core/java/android/app/ApplicationContext.java
+++ b/core/java/android/app/ApplicationContext.java
@@ -1053,11 +1053,6 @@
     }
 
     private SearchManager getSearchManager() {
-        // This is only useable in Activity Contexts
-        if (getActivityToken() == null) {
-            throw new AndroidRuntimeException(
-                "Acquiring SearchManager objects only valid in Activity Contexts.");
-        }
         synchronized (mSync) {
             if (mSearchManager == null) {
                 mSearchManager = new SearchManager(getOuterContext(), mMainThread.getHandler());
diff --git a/core/java/android/app/ApplicationErrorReport.java b/core/java/android/app/ApplicationErrorReport.java
index 6b17236..aeae5f9 100644
--- a/core/java/android/app/ApplicationErrorReport.java
+++ b/core/java/android/app/ApplicationErrorReport.java
@@ -171,6 +171,11 @@
         public String throwMethodName;
 
         /**
+         * Line number the exception was thrown from.
+         */
+        public int throwLineNumber;
+
+        /**
          * Stack trace.
          */
         public String stackTrace;
@@ -190,6 +195,7 @@
             throwFileName = in.readString();
             throwClassName = in.readString();
             throwMethodName = in.readString();
+            throwLineNumber = in.readInt();
             stackTrace = in.readString();
         }
 
@@ -202,6 +208,7 @@
             dest.writeString(throwFileName);
             dest.writeString(throwClassName);
             dest.writeString(throwMethodName);
+            dest.writeInt(throwLineNumber);
             dest.writeString(stackTrace);
         }
 
@@ -214,6 +221,7 @@
             pw.println(prefix + "throwFileName: " + throwFileName);
             pw.println(prefix + "throwClassName: " + throwClassName);
             pw.println(prefix + "throwMethodName: " + throwMethodName);
+            pw.println(prefix + "throwLineNumber: " + throwLineNumber);
             pw.println(prefix + "stackTrace: " + stackTrace);
         }
     }
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 4b64c94..b052c99 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -26,6 +26,7 @@
 import android.content.res.Configuration;
 import android.os.Binder;
 import android.os.Bundle;
+import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.IBinder;
 import android.os.Parcel;
@@ -331,7 +332,9 @@
             data.enforceInterface(IApplicationThread.descriptor);
             boolean start = data.readInt() != 0;
             String path = data.readString();
-            profilerControl(start, path);
+            ParcelFileDescriptor fd = data.readInt() != 0
+                    ? data.readFileDescriptor() : null;
+            profilerControl(start, path, fd);
             return true;
         }
         
@@ -711,11 +714,18 @@
         data.recycle();
     }
     
-    public void profilerControl(boolean start, String path) throws RemoteException {
+    public void profilerControl(boolean start, String path,
+            ParcelFileDescriptor fd) throws RemoteException {
         Parcel data = Parcel.obtain();
         data.writeInterfaceToken(IApplicationThread.descriptor);
         data.writeInt(start ? 1 : 0);
         data.writeString(path);
+        if (fd != null) {
+            data.writeInt(1);
+            fd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+        } else {
+            data.writeInt(0);
+        }
         mRemote.transact(PROFILER_CONTROL_TRANSACTION, data, null,
                 IBinder.FLAG_ONEWAY);
         data.recycle();
diff --git a/core/java/android/app/BackupAgent.java b/core/java/android/app/BackupAgent.java
index 85c001c..e810775 100644
--- a/core/java/android/app/BackupAgent.java
+++ b/core/java/android/app/BackupAgent.java
@@ -78,11 +78,16 @@
      *
      * @param data An open, read-only ParcelFileDescriptor pointing to a full snapshot
      *             of the application's data.
+     * @param appVersionCode The android:versionCode value of the application that backed
+     *        up this particular data set.  This makes it easier for an application's
+     *        agent to distinguish among several possible older data versions when
+     *        asked to perform the restore operation.
      * @param newState An open, read/write ParcelFileDescriptor pointing to an empty
      *                 file.  The application should record the final backup state
      *                 here after restoring its data from dataFd.
      */
-    public abstract void onRestore(BackupDataInput data, ParcelFileDescriptor newState)
+    public abstract void onRestore(BackupDataInput data, int appVersionCode,
+            ParcelFileDescriptor newState)
             throws IOException;
 
 
@@ -121,13 +126,13 @@
             }
         }
 
-        public void doRestore(ParcelFileDescriptor data,
+        public void doRestore(ParcelFileDescriptor data, int appVersionCode,
                 ParcelFileDescriptor newState) throws RemoteException {
             // !!! TODO - real implementation; for now just invoke the callbacks directly
             Log.v(TAG, "doRestore() invoked");
             BackupDataInput input = new BackupDataInput(data.getFileDescriptor());
             try {
-                BackupAgent.this.onRestore(input, newState);
+                BackupAgent.this.onRestore(input, appVersionCode, newState);
             } catch (IOException ex) {
                 Log.d(TAG, "onRestore (" + BackupAgent.this.getClass().getName() + ") threw", ex);
                 throw new RuntimeException(ex);
diff --git a/core/java/android/app/FullBackupAgent.java b/core/java/android/app/FullBackupAgent.java
index 89becf4..d89db96 100644
--- a/core/java/android/app/FullBackupAgent.java
+++ b/core/java/android/app/FullBackupAgent.java
@@ -48,11 +48,11 @@
         }
 
         // That's the file set; now back it all up
-        FileBackupHelper helper = new FileBackupHelper(this);
-        helper.performBackup(oldState, data, newState, (String[])allFiles.toArray());
+        FileBackupHelper helper = new FileBackupHelper(this, (String[])allFiles.toArray());
+        helper.performBackup(oldState, data, newState);
     }
 
     @Override
-    public void onRestore(BackupDataInput data, ParcelFileDescriptor newState) {
+    public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState) {
     }
 }
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 66bc85b..3ec7938 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -250,7 +250,7 @@
     
     // Turn on/off profiling in a particular process.
     public boolean profileControl(String process, boolean start,
-            String path) throws RemoteException;
+            String path, ParcelFileDescriptor fd) throws RemoteException;
     
     public boolean shutdown(int timeout) throws RemoteException;
     
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 029c650..c0bc2a0 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -25,6 +25,7 @@
 import android.content.pm.ServiceInfo;
 import android.content.res.Configuration;
 import android.os.Bundle;
+import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.IBinder;
 import android.os.IInterface;
@@ -92,7 +93,8 @@
     void scheduleLowMemory() throws RemoteException;
     void scheduleActivityConfigurationChanged(IBinder token) throws RemoteException;
     void requestPss() throws RemoteException;
-    void profilerControl(boolean start, String path) throws RemoteException;
+    void profilerControl(boolean start, String path, ParcelFileDescriptor fd)
+            throws RemoteException;
     void setSchedulingGroup(int group) throws RemoteException;
     
     String descriptor = "android.app.IApplicationThread";
diff --git a/core/java/android/app/IBackupAgent.aidl b/core/java/android/app/IBackupAgent.aidl
index bb9f008..9b0550f 100644
--- a/core/java/android/app/IBackupAgent.aidl
+++ b/core/java/android/app/IBackupAgent.aidl
@@ -51,9 +51,14 @@
      *        app's backup.  This is to be a <i>replacement</i> of the app's
      *        current data, not to be merged into it.
      *
+     * @param appVersionCode The android:versionCode attribute of the application
+     *        that created this data set.  This can help the agent distinguish among
+     *        various historical backup content possibilities.
+     *
      * @param newState Read-write file, empty when onRestore() is called,
      *        that is to be written with the state description that holds after
      *        the restore has been completed.
      */
-    void doRestore(in ParcelFileDescriptor data, in ParcelFileDescriptor newState);
+    void doRestore(in ParcelFileDescriptor data, int appVersionCode,
+            in ParcelFileDescriptor newState);
 }
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 3a3a983..6ddf50f 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -44,6 +44,7 @@
 import android.text.InputType;
 import android.text.TextUtils;
 import android.text.TextWatcher;
+import android.text.util.Regex;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.ContextThemeWrapper;
@@ -55,6 +56,7 @@
 import android.view.ViewGroup;
 import android.view.Window;
 import android.view.WindowManager;
+import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.AdapterView;
 import android.widget.AutoCompleteTextView;
@@ -86,13 +88,11 @@
     private static final String INSTANCE_KEY_COMPONENT = "comp";
     private static final String INSTANCE_KEY_APPDATA = "data";
     private static final String INSTANCE_KEY_GLOBALSEARCH = "glob";
-    private static final String INSTANCE_KEY_DISPLAY_QUERY = "dQry";
-    private static final String INSTANCE_KEY_DISPLAY_SEL_START = "sel1";
-    private static final String INSTANCE_KEY_DISPLAY_SEL_END = "sel2";
-    private static final String INSTANCE_KEY_SELECTED_ELEMENT = "slEl";
-    private static final int INSTANCE_SELECTED_BUTTON = -2;
-    private static final int INSTANCE_SELECTED_QUERY = -1;
-    
+    private static final String INSTANCE_KEY_STORED_COMPONENT = "sComp";
+    private static final String INSTANCE_KEY_STORED_APPDATA = "sData";
+    private static final String INSTANCE_KEY_PREVIOUS_COMPONENTS = "sPrev";
+    private static final String INSTANCE_KEY_USER_QUERY = "uQry";
+
     private static final int SEARCH_PLATE_LEFT_PADDING_GLOBAL = 12;
     private static final int SEARCH_PLATE_LEFT_PADDING_NON_GLOBAL = 7;
     
@@ -145,7 +145,10 @@
     // more than once.
     private final WeakHashMap<String, Drawable> mOutsideDrawablesCache =
             new WeakHashMap<String, Drawable>();
-    
+
+    // Last known IME options value for the search edit text.
+    private int mSearchAutoCompleteImeOptions;
+
     /**
      * Constructor - fires it up and makes it look like the search UI.
      * 
@@ -224,6 +227,8 @@
         
         mVoiceAppSearchIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
         mVoiceAppSearchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+        mSearchAutoCompleteImeOptions = mSearchAutoComplete.getImeOptions();
     }
 
     /**
@@ -310,15 +315,17 @@
                     + appSearchData + ", " + globalSearch + ")");
         }
         
+        SearchManager searchManager = (SearchManager)
+                mContext.getSystemService(Context.SEARCH_SERVICE);
         // Try to get the searchable info for the provided component (or for global search,
         // if globalSearch == true).
-        mSearchable = SearchManager.getSearchableInfo(componentName, globalSearch);
+        mSearchable = searchManager.getSearchableInfo(componentName, globalSearch);
         
         // If we got back nothing, and it wasn't a request for global search, then try again
         // for global search, as we'll try to launch that in lieu of any component-specific search.
         if (!globalSearch && mSearchable == null) {
             globalSearch = true;
-            mSearchable = SearchManager.getSearchableInfo(componentName, globalSearch);
+            mSearchable = searchManager.getSearchableInfo(componentName, globalSearch);
             
             // If we still get back null (i.e., there's not even a searchable info available
             // for global search), then really give up.
@@ -333,7 +340,7 @@
         mAppSearchData = appSearchData;
         // Using globalSearch here is just an optimization, just calling
         // isDefaultSearchable() should always give the same result.
-        mGlobalSearchMode = globalSearch || SearchManager.isDefaultSearchable(mSearchable); 
+        mGlobalSearchMode = globalSearch || searchManager.isDefaultSearchable(mSearchable);
         mActivityContext = mSearchable.getActivityContext(getContext());
         
         // show the dialog. this will call onStart().
@@ -441,8 +448,6 @@
     /**
      * Save the minimal set of data necessary to recreate the search
      * 
-     * TODO: go through this and make sure that it saves everything that is needed
-     * 
      * @return A bundle with the state of the dialog.
      */
     @Override
@@ -453,20 +458,11 @@
         bundle.putParcelable(INSTANCE_KEY_COMPONENT, mLaunchComponent);
         bundle.putBundle(INSTANCE_KEY_APPDATA, mAppSearchData);
         bundle.putBoolean(INSTANCE_KEY_GLOBALSEARCH, mGlobalSearchMode);
-        
-        // UI state
-        bundle.putString(INSTANCE_KEY_DISPLAY_QUERY, mSearchAutoComplete.getText().toString());
-        bundle.putInt(INSTANCE_KEY_DISPLAY_SEL_START, mSearchAutoComplete.getSelectionStart());
-        bundle.putInt(INSTANCE_KEY_DISPLAY_SEL_END, mSearchAutoComplete.getSelectionEnd());
-        
-        int selectedElement = INSTANCE_SELECTED_QUERY;
-        if (mGoButton.isFocused()) {
-            selectedElement = INSTANCE_SELECTED_BUTTON;
-        } else if (mSearchAutoComplete.isPopupShowing()) {
-            selectedElement = 0; // TODO mSearchTextField.getListSelection()    // 0..n
-        }
-        bundle.putInt(INSTANCE_KEY_SELECTED_ELEMENT, selectedElement);
-        
+        bundle.putParcelable(INSTANCE_KEY_STORED_COMPONENT, mStoredComponentName);
+        bundle.putBundle(INSTANCE_KEY_STORED_APPDATA, mStoredAppSearchData);
+        bundle.putParcelableArrayList(INSTANCE_KEY_PREVIOUS_COMPONENTS, mPreviousComponents);
+        bundle.putString(INSTANCE_KEY_USER_QUERY, mUserQuery);
+
         return bundle;
     }
 
@@ -480,45 +476,27 @@
      */
     @Override
     public void onRestoreInstanceState(Bundle savedInstanceState) {
-        // Get the launch info
         ComponentName launchComponent = savedInstanceState.getParcelable(INSTANCE_KEY_COMPONENT);
         Bundle appSearchData = savedInstanceState.getBundle(INSTANCE_KEY_APPDATA);
         boolean globalSearch = savedInstanceState.getBoolean(INSTANCE_KEY_GLOBALSEARCH);
-        
-        // get the UI state
-        String displayQuery = savedInstanceState.getString(INSTANCE_KEY_DISPLAY_QUERY);
-        int querySelStart = savedInstanceState.getInt(INSTANCE_KEY_DISPLAY_SEL_START, -1);
-        int querySelEnd = savedInstanceState.getInt(INSTANCE_KEY_DISPLAY_SEL_END, -1);
-        int selectedElement = savedInstanceState.getInt(INSTANCE_KEY_SELECTED_ELEMENT);
-        
-        // show the dialog.  skip any show/hide animation, we want to go fast.
-        // send the text that actually generates the suggestions here;  we'll replace the display
-        // text as necessary in a moment.
-        if (!show(displayQuery, false, launchComponent, appSearchData, globalSearch)) {
+        ComponentName storedComponentName =
+                savedInstanceState.getParcelable(INSTANCE_KEY_STORED_COMPONENT);
+        Bundle storedAppSearchData =
+                savedInstanceState.getBundle(INSTANCE_KEY_STORED_APPDATA);
+        ArrayList<ComponentName> previousComponents =
+                savedInstanceState.getParcelableArrayList(INSTANCE_KEY_PREVIOUS_COMPONENTS);
+        String userQuery = savedInstanceState.getString(INSTANCE_KEY_USER_QUERY);
+
+        // Set stored state
+        mStoredComponentName = storedComponentName;
+        mStoredAppSearchData = storedAppSearchData;
+        mPreviousComponents = previousComponents;
+
+        // show the dialog.
+        if (!doShow(userQuery, false, launchComponent, appSearchData, globalSearch)) {
             // for some reason, we couldn't re-instantiate
             return;
         }
-        
-        mSearchAutoComplete.setText(displayQuery);
-        
-        // clean up the selection state
-        switch (selectedElement) {
-        case INSTANCE_SELECTED_BUTTON:
-            mGoButton.setEnabled(true);
-            mGoButton.setFocusable(true);
-            mGoButton.requestFocus();
-            break;
-        case INSTANCE_SELECTED_QUERY:
-            if (querySelStart >= 0 && querySelEnd >= 0) {
-                mSearchAutoComplete.requestFocus();
-                mSearchAutoComplete.setSelection(querySelStart, querySelEnd);
-            }
-            break;
-        default:
-            // TODO: defer selecting a list element until suggestion list appears
-//            mSearchAutoComplete.setListSelection(selectedElement)
-            break;
-        }
     }
     
     /**
@@ -563,7 +541,8 @@
                 }
             }
             mSearchAutoComplete.setInputType(inputType);
-            mSearchAutoComplete.setImeOptions(mSearchable.getImeOptions());
+            mSearchAutoCompleteImeOptions = mSearchable.getImeOptions();
+            mSearchAutoComplete.setImeOptions(mSearchAutoCompleteImeOptions);
         }
     }
     
@@ -581,12 +560,8 @@
 
         if (mGlobalSearchMode) {
             mSearchAutoComplete.setDropDownAlwaysVisible(true);  // fill space until results come in
-            mSearchAutoComplete.setDropDownBackgroundResource(
-                    com.android.internal.R.drawable.search_dropdown_background);
         } else {
             mSearchAutoComplete.setDropDownAlwaysVisible(false);
-            mSearchAutoComplete.setDropDownBackgroundResource(
-                    com.android.internal.R.drawable.search_dropdown_background_apps);
         }
 
         // attach the suggestions adapter, if suggestions are available
@@ -794,7 +769,24 @@
             }
         }
 
-        public void afterTextChanged(Editable s) { }
+        public void afterTextChanged(Editable s) {
+            if (!mSearchAutoComplete.isPerformingCompletion()) {
+                // The user changed the query, check if it is a URL and if so change the search
+                // button in the soft keyboard to the 'Go' button.
+                int options = (mSearchAutoComplete.getImeOptions() & (~EditorInfo.IME_MASK_ACTION));
+                if (Regex.WEB_URL_PATTERN.matcher(mUserQuery).matches()) {
+                    options = options | EditorInfo.IME_ACTION_GO;
+                } else {
+                    options = options | EditorInfo.IME_ACTION_SEARCH;
+                }
+                if (options != mSearchAutoCompleteImeOptions) {
+                    mSearchAutoCompleteImeOptions = options;
+                    mSearchAutoComplete.setImeOptions(options);
+                    // This call is required to update the soft keyboard UI with latest IME flags.
+                    mSearchAutoComplete.setInputType(mSearchAutoComplete.getInputType());
+                }
+            }
+        }
     };
 
     /**
@@ -932,6 +924,32 @@
     }
 
     /**
+     * Corrects http/https typo errors in the given url string, and if the protocol specifier was
+     * not present defaults to http.
+     * 
+     * @param inUrl URL to check and fix
+     * @return fixed URL string.
+     */
+    private String fixUrl(String inUrl) {
+        if (inUrl.startsWith("http://") || inUrl.startsWith("https://"))
+            return inUrl;
+
+        if (inUrl.startsWith("http:") || inUrl.startsWith("https:")) {
+            if (inUrl.startsWith("http:/") || inUrl.startsWith("https:/")) {
+                inUrl = inUrl.replaceFirst("/", "//");
+            } else {
+                inUrl = inUrl.replaceFirst(":", "://");
+            }
+        }
+
+        if (inUrl.indexOf("://") == -1) {
+            inUrl = "http://" + inUrl;
+        }
+
+        return inUrl;
+    }
+
+    /**
      * React to the user typing "enter" or other hardwired keys while typing in the search box.
      * This handles these special keys while the edit box has focus.
      */
@@ -961,7 +979,19 @@
                 if (keyCode == KeyEvent.KEYCODE_ENTER 
                         && event.getAction() == KeyEvent.ACTION_UP) {
                     v.cancelLongPress();
-                    launchQuerySearch();                    
+
+                    // If this is a url entered by the user and we displayed the 'Go' button which
+                    // the user clicked, launch the url instead of using it as a search query.
+                    if ((mSearchAutoCompleteImeOptions & EditorInfo.IME_MASK_ACTION)
+                            == EditorInfo.IME_ACTION_GO) {
+                        Uri uri = Uri.parse(fixUrl(mSearchAutoComplete.getText().toString()));
+                        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
+                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                        launchIntent(intent);
+                    } else {
+                        // Launch as a regular search.
+                        launchQuerySearch();
+                    }
                     return true;
                 }
                 if (event.getAction() == KeyEvent.ACTION_DOWN) {
@@ -1292,6 +1322,7 @@
 
         String query = intent.getStringExtra(SearchManager.QUERY);
         setUserQuery(query);
+        mSearchAutoComplete.showDropDown();
     }
 
     /**
@@ -1440,6 +1471,7 @@
         if (data != null) {
             intent.setData(data);
         }
+        intent.putExtra(SearchManager.USER_QUERY, mUserQuery);
         if (query != null) {
             intent.putExtra(SearchManager.QUERY, query);
         }
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index eb80400..e5ba6a4 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -1136,6 +1136,20 @@
     public final static String QUERY = "query";
 
     /**
+     * Intent extra data key: Use this key with
+     * {@link android.content.Intent#getStringExtra
+     *  content.Intent.getStringExtra()}
+     * to obtain the query string typed in by the user.
+     * This may be different from the value of {@link #QUERY}
+     * if the intent is the result of selecting a suggestion.
+     * In that case, {@link #QUERY} will contain the value of
+     * {@link #SUGGEST_COLUMN_QUERY} for the suggestion, and
+     * {@link #USER_QUERY} will contain the string typed by the
+     * user.
+     */
+    public final static String USER_QUERY = "user_query";
+
+    /**
      * Intent extra data key: Use this key with Intent.ACTION_SEARCH and
      * {@link android.content.Intent#getBundleExtra
      *  content.Intent.getBundleExtra()}
@@ -1514,7 +1528,7 @@
     /**
      * Reference to the shared system search service.
      */
-    private static ISearchManager sService = getSearchManagerService();
+    private static ISearchManager mService;
 
     private final Context mContext;
 
@@ -1529,6 +1543,8 @@
     /*package*/ SearchManager(Context context, Handler handler)  {
         mContext = context;
         mHandler = handler;
+        mService = ISearchManager.Stub.asInterface(
+                ServiceManager.getService(Context.SEARCH_SERVICE));
     }
     
     /**
@@ -1581,7 +1597,7 @@
         try {
             mIsShowing = true;
             // activate the search manager and start it up!
-            sService.startSearch(initialQuery, selectInitialQuery, launchActivity, appSearchData,
+            mService.startSearch(initialQuery, selectInitialQuery, launchActivity, appSearchData,
                     globalSearch, mSearchManagerCallback);
         } catch (RemoteException ex) {
             Log.e(TAG, "startSearch() failed: " + ex);
@@ -1603,7 +1619,7 @@
         if (DBG) debug("stopSearch(), mIsShowing=" + mIsShowing);
         if (!mIsShowing) return;
         try {
-            sService.stopSearch();
+            mService.stopSearch();
             // onDismiss will also clear this, but we do it here too since onDismiss() is
             // called asynchronously.
             mIsShowing = false;
@@ -1725,7 +1741,7 @@
         if (DBG) debug("saveSearchDialog(), mIsShowing=" + mIsShowing);
         if (!mIsShowing) return null;
         try {
-            return sService.onSaveInstanceState();
+            return mService.onSaveInstanceState();
         } catch (RemoteException ex) {
             Log.e(TAG, "onSaveInstanceState() failed: " + ex);
             return null;
@@ -1743,7 +1759,7 @@
         if (DBG) debug("restoreSearchDialog(" + searchDialogState + ")");
         if (searchDialogState == null) return;
         try {
-            sService.onRestoreInstanceState(searchDialogState);
+            mService.onRestoreInstanceState(searchDialogState);
         } catch (RemoteException ex) {
             Log.e(TAG, "onRestoreInstanceState() failed: " + ex);
         }
@@ -1760,17 +1776,12 @@
         if (DBG) debug("onConfigurationChanged(" + newConfig + "), mIsShowing=" + mIsShowing);
         if (!mIsShowing) return;
         try {
-            sService.onConfigurationChanged(newConfig);
+            mService.onConfigurationChanged(newConfig);
         } catch (RemoteException ex) {
             Log.e(TAG, "onConfigurationChanged() failed:" + ex);
         }
     }
 
-    private static ISearchManager getSearchManagerService() {
-        return ISearchManager.Stub.asInterface(
-            ServiceManager.getService(Context.SEARCH_SERVICE));
-    }
-    
     /**
      * Gets information about a searchable activity. This method is static so that it can
      * be used from non-Activity contexts.
@@ -1782,10 +1793,10 @@
      * 
      * @hide because SearchableInfo is not part of the API.
      */
-    public static SearchableInfo getSearchableInfo(ComponentName componentName, 
+    public SearchableInfo getSearchableInfo(ComponentName componentName,
             boolean globalSearch) {
         try {
-            return sService.getSearchableInfo(componentName, globalSearch);
+            return mService.getSearchableInfo(componentName, globalSearch);
         } catch (RemoteException ex) {
             Log.e(TAG, "getSearchableInfo() failed: " + ex);
             return null;
@@ -1797,23 +1808,22 @@
      * 
      * @hide because SearchableInfo is not part of the API.
      */
-    public static boolean isDefaultSearchable(SearchableInfo searchable) {
-        SearchableInfo defaultSearchable = SearchManager.getSearchableInfo(null, true);
+    public boolean isDefaultSearchable(SearchableInfo searchable) {
+        SearchableInfo defaultSearchable = getSearchableInfo(null, true);
         return defaultSearchable != null 
                 && defaultSearchable.getSearchActivity().equals(searchable.getSearchActivity());
     }
-    
+
     /**
-     * Gets a cursor with search suggestions. This method is static so that it can
-     * be used from non-Activity context.
+     * Gets a cursor with search suggestions.
      *
      * @param searchable Information about how to get the suggestions.
      * @param query The search text entered (so far).
-     * @return a cursor with suggestions, or <code>null</null> the suggestion query failed. 
-     * 
+     * @return a cursor with suggestions, or <code>null</null> the suggestion query failed.
+     *
      * @hide because SearchableInfo is not part of the API.
      */
-    public static Cursor getSuggestions(Context context, SearchableInfo searchable, String query) {
+    public Cursor getSuggestions(SearchableInfo searchable, String query) {
         if (searchable == null) {
             return null;
         }
@@ -1852,7 +1862,7 @@
                 .build();
 
         // finally, make the query
-        return context.getContentResolver().query(uri, null, selection, selArgs, null);
+        return mContext.getContentResolver().query(uri, null, selection, selArgs, null);
     }
      
     /**
@@ -1864,9 +1874,9 @@
      * 
      * @hide because SearchableInfo is not part of the API.
      */
-    public static List<SearchableInfo> getSearchablesInGlobalSearch() {
+    public List<SearchableInfo> getSearchablesInGlobalSearch() {
         try {
-            return sService.getSearchablesInGlobalSearch();
+            return mService.getSearchablesInGlobalSearch();
         } catch (RemoteException e) {
             Log.e(TAG, "getSearchablesInGlobalSearch() failed: " + e);
             return null;
@@ -1881,9 +1891,9 @@
      *
      * @hide because SearchableInfo is not part of the API.
      */
-    public static List<SearchableInfo> getSearchablesForWebSearch() {
+    public List<SearchableInfo> getSearchablesForWebSearch() {
         try {
-            return sService.getSearchablesForWebSearch();
+            return mService.getSearchablesForWebSearch();
         } catch (RemoteException e) {
             Log.e(TAG, "getSearchablesForWebSearch() failed: " + e);
             return null;
@@ -1897,9 +1907,9 @@
      *
      * @hide because SearchableInfo is not part of the API.
      */
-    public static SearchableInfo getDefaultSearchableForWebSearch() {
+    public SearchableInfo getDefaultSearchableForWebSearch() {
         try {
-            return sService.getDefaultSearchableForWebSearch();
+            return mService.getDefaultSearchableForWebSearch();
         } catch (RemoteException e) {
             Log.e(TAG, "getDefaultSearchableForWebSearch() failed: " + e);
             return null;
@@ -1913,9 +1923,9 @@
      *
      * @hide
      */
-    public static void setDefaultWebSearch(ComponentName component) {
+    public void setDefaultWebSearch(ComponentName component) {
         try {
-            sService.setDefaultWebSearch(component);
+            mService.setDefaultWebSearch(component);
         } catch (RemoteException e) {
             Log.e(TAG, "setDefaultWebSearch() failed: " + e);
         }
diff --git a/core/java/android/app/SuggestionsAdapter.java b/core/java/android/app/SuggestionsAdapter.java
index ed76f4e..49c94d1 100644
--- a/core/java/android/app/SuggestionsAdapter.java
+++ b/core/java/android/app/SuggestionsAdapter.java
@@ -54,6 +54,7 @@
     private static final boolean DBG = false;
     private static final String LOG_TAG = "SuggestionsAdapter";
 
+    private SearchManager mSearchManager;
     private SearchDialog mSearchDialog;
     private SearchableInfo mSearchable;
     private Context mProviderContext;
@@ -92,6 +93,7 @@
                 com.android.internal.R.layout.search_dropdown_item_icons_2line,
                 null,   // no initial cursor
                 true);  // auto-requery
+        mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
         mSearchDialog = searchDialog;
         mSearchable = searchable;
 
@@ -142,10 +144,10 @@
             mSearchDialog.getWindow().getDecorView().post(mStartSpinnerRunnable);
         }
         try {
-            final Cursor cursor = SearchManager.getSuggestions(mContext, mSearchable, query);
+            final Cursor cursor = mSearchManager.getSuggestions(mSearchable, query);
             // trigger fill window so the spinner stays up until the results are copied over and
             // closer to being ready
-            if (!mGlobalSearchMode) cursor.getCount();
+            if (!mGlobalSearchMode && cursor != null) cursor.getCount();
             return cursor;
         } catch (RuntimeException e) {
             Log.w(LOG_TAG, "Search suggestions query threw an exception.", e);
diff --git a/core/java/android/backup/BackupDataOutput.java b/core/java/android/backup/BackupDataOutput.java
index 05e667e..d29c5ba 100644
--- a/core/java/android/backup/BackupDataOutput.java
+++ b/core/java/android/backup/BackupDataOutput.java
@@ -55,6 +55,10 @@
         }
     }
 
+    public void setKeyPrefix(String keyPrefix) {
+        setKeyPrefix_native(mBackupWriter, keyPrefix);
+    }
+
     protected void finalize() throws Throwable {
         try {
             dtor(mBackupWriter);
@@ -62,11 +66,12 @@
             super.finalize();
         }
     }
-        
+
     private native static int ctor(FileDescriptor fd);
     private native static void dtor(int mBackupWriter);
 
     private native static int writeEntityHeader_native(int mBackupWriter, String key, int dataSize);
     private native static int writeEntityData_native(int mBackupWriter, byte[] data, int size);
+    private native static void setKeyPrefix_native(int mBackupWriter, String keyPrefix);
 }
 
diff --git a/core/java/android/backup/RestoreHelper.java b/core/java/android/backup/BackupHelper.java
similarity index 63%
rename from core/java/android/backup/RestoreHelper.java
rename to core/java/android/backup/BackupHelper.java
index e47869c..3983e28 100644
--- a/core/java/android/backup/RestoreHelper.java
+++ b/core/java/android/backup/BackupHelper.java
@@ -21,14 +21,26 @@
 import java.io.InputStream;
 
 /** @hide */
-public interface RestoreHelper {
+public interface BackupHelper {
     /**
-     * Called by RestoreHelperDispatcher to dispatch one entity of data.
+     * Based on oldState, determine which of the files from the application's data directory
+     * need to be backed up, write them to the data stream, and fill in newState with the
+     * state as it exists now.
+     */
+    public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
+            ParcelFileDescriptor newState);
+
+    /**
+     * Called by BackupHelperDispatcher to dispatch one entity of data.
      * <p class=note>
      * Do not close the <code>data</code> stream.  Do not read more than
      * <code>dataSize</code> bytes from <code>data</code>.
      */
     public void restoreEntity(BackupDataInputStream data);
-    public void writeSnapshot(ParcelFileDescriptor fd);
+
+    /**
+     *
+     */
+    public void writeRestoreSnapshot(ParcelFileDescriptor fd);
 }
 
diff --git a/core/java/android/backup/BackupHelperAgent.java b/core/java/android/backup/BackupHelperAgent.java
new file mode 100644
index 0000000..3720d50
--- /dev/null
+++ b/core/java/android/backup/BackupHelperAgent.java
@@ -0,0 +1,56 @@
+/*
+ * 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.backup;
+
+import android.app.BackupAgent;
+import android.backup.BackupHelper;
+import android.backup.BackupHelperDispatcher;
+import android.backup.BackupDataInput;
+import android.backup.BackupDataOutput;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+import java.io.IOException;
+
+/** @hide */
+public class BackupHelperAgent extends BackupAgent {
+    static final String TAG = "BackupHelperAgent";
+
+    BackupHelperDispatcher mDispatcher = new BackupHelperDispatcher();
+
+    @Override
+    public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
+             ParcelFileDescriptor newState) {
+        mDispatcher.performBackup(oldState, data, newState);
+    }
+
+    @Override
+    public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
+            throws IOException {
+        mDispatcher.performRestore(data, appVersionCode, newState);
+    }
+
+    public BackupHelperDispatcher getDispatcher() {
+        return mDispatcher;
+    }
+
+    public void addHelper(String keyPrefix, BackupHelper helper) {
+        mDispatcher.addHelper(keyPrefix, helper);
+    }
+}
+
+
diff --git a/core/java/android/backup/RestoreHelperDispatcher.java b/core/java/android/backup/BackupHelperDispatcher.java
similarity index 61%
rename from core/java/android/backup/RestoreHelperDispatcher.java
rename to core/java/android/backup/BackupHelperDispatcher.java
index 4861775..b25c3e3 100644
--- a/core/java/android/backup/RestoreHelperDispatcher.java
+++ b/core/java/android/backup/BackupHelperDispatcher.java
@@ -20,20 +20,35 @@
 import android.util.Log;
 
 import java.io.IOException;
-import java.util.HashMap;
+import java.util.TreeMap;
 import java.util.Map;
 
 /** @hide */
-public class RestoreHelperDispatcher {
-    private static final String TAG = "RestoreHelperDispatcher";
+public class BackupHelperDispatcher {
+    private static final String TAG = "BackupHelperDispatcher";
 
-    HashMap<String,RestoreHelper> mHelpers = new HashMap<String,RestoreHelper>();
+    TreeMap<String,BackupHelper> mHelpers = new TreeMap<String,BackupHelper>();
+    
+    public BackupHelperDispatcher() {
+    }
 
-    public void addHelper(String keyPrefix, RestoreHelper helper) {
+    public void addHelper(String keyPrefix, BackupHelper helper) {
         mHelpers.put(keyPrefix, helper);
     }
 
-    public void dispatch(BackupDataInput input, ParcelFileDescriptor newState) throws IOException {
+    /** TODO: Make this save and restore the key prefix. */
+    public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
+             ParcelFileDescriptor newState) {
+        // Write out the state files -- mHelpers is a TreeMap, so the order is well defined.
+        for (Map.Entry<String,BackupHelper> entry: mHelpers.entrySet()) {
+            data.setKeyPrefix(entry.getKey());
+            entry.getValue().performBackup(oldState, data, newState);
+        }
+    }
+
+    public void performRestore(BackupDataInput input, int appVersionCode,
+            ParcelFileDescriptor newState)
+            throws IOException {
         boolean alreadyComplained = false;
 
         BackupDataInputStream stream = new BackupDataInputStream(input);
@@ -43,7 +58,7 @@
             int pos = rawKey.indexOf(':');
             if (pos > 0) {
                 String prefix = rawKey.substring(0, pos);
-                RestoreHelper helper = mHelpers.get(prefix);
+                BackupHelper helper = mHelpers.get(prefix);
                 if (helper != null) {
                     stream.dataSize = input.getDataSize();
                     stream.key = rawKey.substring(pos+1);
@@ -63,15 +78,9 @@
             input.skipEntityData(); // In case they didn't consume the data.
         }
 
-        if (mHelpers.size() > 1) {
-            throw new RuntimeException("RestoreHelperDispatcher won't get your your"
-                    + " data in the right order yet.");
-        }
-        
-        // Write out the state files
-        for (RestoreHelper helper: mHelpers.values()) {
-            // TODO: Write a header for the state
-            helper.writeSnapshot(newState);
+        // Write out the state files -- mHelpers is a TreeMap, so the order is well defined.
+        for (BackupHelper helper: mHelpers.values()) {
+            helper.writeRestoreSnapshot(newState);
         }
     }
 }
diff --git a/core/java/android/backup/FileBackupHelper.java b/core/java/android/backup/FileBackupHelper.java
index ed840bb..4058497 100644
--- a/core/java/android/backup/FileBackupHelper.java
+++ b/core/java/android/backup/FileBackupHelper.java
@@ -24,19 +24,19 @@
 import java.io.FileDescriptor;
 
 /** @hide */
-public class FileBackupHelper {
+public class FileBackupHelper extends FileBackupHelperBase implements BackupHelper {
     private static final String TAG = "FileBackupHelper";
 
     Context mContext;
-    String mKeyPrefix;
+    File mFilesDir;
+    String[] mFiles;
 
-    public FileBackupHelper(Context context) {
-        mContext = context;
-    }
+    public FileBackupHelper(Context context, String... files) {
+        super(context);
 
-    public FileBackupHelper(Context context, String keyPrefix) {
         mContext = context;
-        mKeyPrefix = keyPrefix;
+        mFilesDir = context.getFilesDir();
+        mFiles = files;
     }
 
     /**
@@ -45,8 +45,9 @@
      * state as it exists now.
      */
     public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
-            ParcelFileDescriptor newState, String[] files) {
+            ParcelFileDescriptor newState) {
         // file names
+        String[] files = mFiles;
         File base = mContext.getFilesDir();
         final int N = files.length;
         String[] fullPaths = new String[N];
@@ -54,66 +55,18 @@
             fullPaths[i] = (new File(base, files[i])).getAbsolutePath();
         }
 
-        // keys
-        String[] keys = makeKeys(mKeyPrefix, files);
-
         // go
-        performBackup_checked(oldState, data, newState, fullPaths, keys);
+        performBackup_checked(oldState, data, newState, fullPaths, files);
     }
 
-    /**
-     * If keyPrefix is not null, prepend it to each of the strings in <code>original</code>;
-     * otherwise, return original.
-     */
-    static String[] makeKeys(String keyPrefix, String[] original) {
-        if (keyPrefix != null) {
-            String[] keys;
-            final int N = original.length;
-            keys = new String[N];
-            for (int i=0; i<N; i++) {
-                keys[i] = keyPrefix + ':' + original[i];
-            }
-            return keys;
-        } else {
-            return original;
+    public void restoreEntity(BackupDataInputStream data) {
+        // TODO: turn this off before ship
+        Log.d(TAG, "got entity '" + data.getKey() + "' size=" + data.size());
+        String key = data.getKey();
+        if (isKeyInList(key, mFiles)) {
+            File f = new File(mFilesDir, key);
+            writeFile(f, data);
         }
     }
-
-    /**
-     * Check the parameters so the native code doens't have to throw all the exceptions
-     * since it's easier to do that from java.
-     */
-    static void performBackup_checked(ParcelFileDescriptor oldState, BackupDataOutput data,
-            ParcelFileDescriptor newState, String[] files, String[] keys) {
-        if (files.length == 0) {
-            return;
-        }
-        // files must be all absolute paths
-        for (String f: files) {
-            if (f.charAt(0) != '/') {
-                throw new RuntimeException("files must have all absolute paths: " + f);
-            }
-        }
-        // the length of files and keys must be the same
-        if (files.length != keys.length) {
-            throw new RuntimeException("files.length=" + files.length
-                    + " keys.length=" + keys.length);
-        }
-        // oldStateFd can be null
-        FileDescriptor oldStateFd = oldState != null ? oldState.getFileDescriptor() : null;
-        FileDescriptor newStateFd = newState.getFileDescriptor();
-        if (newStateFd == null) {
-            throw new NullPointerException();
-        }
-
-        int err = performBackup_native(oldStateFd, data.mBackupWriter, newStateFd, files, keys);
-
-        if (err != 0) {
-            // TODO: more here
-            throw new RuntimeException("Backup failed 0x" + Integer.toHexString(err));
-        }
-    }
-
-    native private static int performBackup_native(FileDescriptor oldState,
-            int data, FileDescriptor newState, String[] files, String[] keys);
 }
+
diff --git a/core/java/android/backup/FileBackupHelperBase.java b/core/java/android/backup/FileBackupHelperBase.java
new file mode 100644
index 0000000..03ae476
--- /dev/null
+++ b/core/java/android/backup/FileBackupHelperBase.java
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ */
+
+package android.backup;
+
+import android.content.Context;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+import java.io.InputStream;
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+
+class FileBackupHelperBase {
+    private static final String TAG = "RestoreHelperBase";
+
+    int mPtr;
+    Context mContext;
+    boolean mExceptionLogged;
+    
+    FileBackupHelperBase(Context context) {
+        mPtr = ctor();
+        mContext = context;
+    }
+
+    protected void finalize() throws Throwable {
+        try {
+            dtor(mPtr);
+        } finally {
+            super.finalize();
+        }
+    }
+
+    /**
+     * Check the parameters so the native code doens't have to throw all the exceptions
+     * since it's easier to do that from java.
+     */
+    static void performBackup_checked(ParcelFileDescriptor oldState, BackupDataOutput data,
+            ParcelFileDescriptor newState, String[] files, String[] keys) {
+        if (files.length == 0) {
+            return;
+        }
+        // files must be all absolute paths
+        for (String f: files) {
+            if (f.charAt(0) != '/') {
+                throw new RuntimeException("files must have all absolute paths: " + f);
+            }
+        }
+        // the length of files and keys must be the same
+        if (files.length != keys.length) {
+            throw new RuntimeException("files.length=" + files.length
+                    + " keys.length=" + keys.length);
+        }
+        // oldStateFd can be null
+        FileDescriptor oldStateFd = oldState != null ? oldState.getFileDescriptor() : null;
+        FileDescriptor newStateFd = newState.getFileDescriptor();
+        if (newStateFd == null) {
+            throw new NullPointerException();
+        }
+
+        int err = performBackup_native(oldStateFd, data.mBackupWriter, newStateFd, files, keys);
+
+        if (err != 0) {
+            // TODO: more here
+            throw new RuntimeException("Backup failed 0x" + Integer.toHexString(err));
+        }
+    }
+
+    void writeFile(File f, InputStream in) {
+        if (!(in instanceof BackupDataInputStream)) {
+            throw new IllegalStateException("input stream must be a BackupDataInputStream");
+        }
+        int result = -1;
+
+        // Create the enclosing directory.
+        File parent = f.getParentFile();
+        parent.mkdirs();
+
+        result = writeFile_native(mPtr, f.getAbsolutePath(),
+                ((BackupDataInputStream)in).mData.mBackupReader);
+        if (result != 0) {
+            // Bail on this entity.  Only log one failure per helper object.
+            if (!mExceptionLogged) {
+                Log.e(TAG, "Failed restoring file '" + f + "' for app '"
+                        + mContext.getPackageName() + "\' result=0x"
+                        + Integer.toHexString(result));
+                mExceptionLogged = true;
+            }
+        }
+    }
+
+    public void writeRestoreSnapshot(ParcelFileDescriptor fd) {
+        int result = writeSnapshot_native(mPtr, fd.getFileDescriptor());
+        // TODO: Do something with the error.
+    }
+
+    boolean isKeyInList(String key, String[] list) {
+        for (String s: list) {
+            if (s.equals(key)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static native int ctor();
+    private static native void dtor(int ptr);
+
+    native private static int performBackup_native(FileDescriptor oldState,
+            int data, FileDescriptor newState, String[] files, String[] keys);
+    
+    private static native int writeFile_native(int ptr, String filename, int backupReader);
+    private static native int writeSnapshot_native(int ptr, FileDescriptor fd);
+}
+
+
diff --git a/core/java/android/backup/FileRestoreHelper.java b/core/java/android/backup/FileRestoreHelper.java
deleted file mode 100644
index b7e3625..0000000
--- a/core/java/android/backup/FileRestoreHelper.java
+++ /dev/null
@@ -1,41 +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.
- */
-
-package android.backup;
-
-import android.content.Context;
-import android.util.Log;
-
-import java.io.File;
-
-/** @hide */
-public class FileRestoreHelper extends RestoreHelperBase implements RestoreHelper {
-    private static final String TAG = "FileRestoreHelper";
-
-    File mFilesDir;
-
-    public FileRestoreHelper(Context context) {
-        super(context);
-        mFilesDir = context.getFilesDir();
-    }
-
-    public void restoreEntity(BackupDataInputStream data) {
-        Log.d(TAG, "got entity '" + data.getKey() + "' size=" + data.size()); // TODO: turn this off before ship
-        File f = new File(mFilesDir, data.getKey());
-        writeFile(f, data);
-    }
-}
-
diff --git a/core/java/android/backup/IBackupManager.aidl b/core/java/android/backup/IBackupManager.aidl
index efc664c..d6283d0 100644
--- a/core/java/android/backup/IBackupManager.aidl
+++ b/core/java/android/backup/IBackupManager.aidl
@@ -33,19 +33,19 @@
      * Tell the system service that the caller has made changes to its
      * data, and therefore needs to undergo an incremental backup pass.
      */
-    oneway void dataChanged(String packageName);
+    void dataChanged(String packageName);
 
     /**
      * Notifies the Backup Manager Service that an agent has become available.  This
      * method is only invoked by the Activity Manager.
      */
-    oneway void agentConnected(String packageName, IBinder agent);
+    void agentConnected(String packageName, IBinder agent);
 
     /**
      * Notify the Backup Manager Service that an agent has unexpectedly gone away.
      * This method is only invoked by the Activity Manager.
      */
-    oneway void agentDisconnected(String packageName);
+    void agentDisconnected(String packageName);
 
     /**
      * Schedule an immediate backup attempt for all pending updates.  This is
@@ -57,7 +57,7 @@
      *
      * <p>Callers must hold the android.permission.BACKUP permission to use this method.
      */
-    oneway void backupNow();
+    void backupNow();
 
     /**
      * Identify the currently selected transport.  Callers must hold the
diff --git a/core/java/android/backup/RestoreHelperBase.java b/core/java/android/backup/RestoreHelperBase.java
deleted file mode 100644
index 93a8fef..0000000
--- a/core/java/android/backup/RestoreHelperBase.java
+++ /dev/null
@@ -1,82 +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.
- */
-
-package android.backup;
-
-import android.content.Context;
-import android.os.ParcelFileDescriptor;
-import android.util.Log;
-
-import java.io.InputStream;
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileOutputStream;
-
-class RestoreHelperBase {
-    private static final String TAG = "RestoreHelperBase";
-
-    int mPtr;
-    Context mContext;
-    boolean mExceptionLogged;
-    
-    RestoreHelperBase(Context context) {
-        mPtr = ctor();
-        mContext = context;
-    }
-
-    protected void finalize() throws Throwable {
-        try {
-            dtor(mPtr);
-        } finally {
-            super.finalize();
-        }
-    }
-
-    void writeFile(File f, InputStream in) {
-        if (!(in instanceof BackupDataInputStream)) {
-            throw new IllegalStateException("input stream must be a BackupDataInputStream");
-        }
-        int result = -1;
-
-        // Create the enclosing directory.
-        File parent = f.getParentFile();
-        parent.mkdirs();
-
-        result = writeFile_native(mPtr, f.getAbsolutePath(),
-                ((BackupDataInputStream)in).mData.mBackupReader);
-        if (result != 0) {
-            // Bail on this entity.  Only log one failure per helper object.
-            if (!mExceptionLogged) {
-                Log.e(TAG, "Failed restoring file '" + f + "' for app '"
-                        + mContext.getPackageName() + "\' result=0x"
-                        + Integer.toHexString(result));
-                mExceptionLogged = true;
-            }
-        }
-    }
-
-    public void writeSnapshot(ParcelFileDescriptor fd) {
-        int result = writeSnapshot_native(mPtr, fd.getFileDescriptor());
-        // TODO: Do something with the error.
-    }
-
-    private static native int ctor();
-    private static native void dtor(int ptr);
-    private static native int writeFile_native(int ptr, String filename, int backupReader);
-    private static native int writeSnapshot_native(int ptr, FileDescriptor fd);
-}
-
-
diff --git a/core/java/android/backup/RestoreSet.java b/core/java/android/backup/RestoreSet.java
index 96a99ae..eeca148 100644
--- a/core/java/android/backup/RestoreSet.java
+++ b/core/java/android/backup/RestoreSet.java
@@ -43,14 +43,14 @@
      * transport.  This is guaranteed to be valid for the duration of a restore
      * session, but is meaningless once the session has ended.
      */
-    public int token;
+    public long token;
 
 
     public RestoreSet() {
         // Leave everything zero / null
     }
 
-    public RestoreSet(String _name, String _dev, int _token) {
+    public RestoreSet(String _name, String _dev, long _token) {
         name = _name;
         device = _dev;
         token = _token;
@@ -65,7 +65,7 @@
     public void writeToParcel(Parcel out, int flags) {
         out.writeString(name);
         out.writeString(device);
-        out.writeInt(token);
+        out.writeLong(token);
     }
 
     public static final Parcelable.Creator<RestoreSet> CREATOR
@@ -82,6 +82,6 @@
     private RestoreSet(Parcel in) {
         name = in.readString();
         device = in.readString();
-        token = in.readInt();
+        token = in.readLong();
     }
-}
\ No newline at end of file
+}
diff --git a/core/java/android/backup/SharedPreferencesBackupHelper.java b/core/java/android/backup/SharedPreferencesBackupHelper.java
index cad79df..f492629 100644
--- a/core/java/android/backup/SharedPreferencesBackupHelper.java
+++ b/core/java/android/backup/SharedPreferencesBackupHelper.java
@@ -18,39 +18,51 @@
 
 import android.content.Context;
 import android.os.ParcelFileDescriptor;
+import android.util.Log;
 
+import java.io.File;
 import java.io.FileDescriptor;
 
 /** @hide */
-public class SharedPreferencesBackupHelper {
+public class SharedPreferencesBackupHelper extends FileBackupHelperBase implements BackupHelper {
+    private static final String TAG = "SharedPreferencesBackupHelper";
+
     private Context mContext;
-    private String mKeyPrefix;
+    private String[] mPrefGroups;
 
-    public SharedPreferencesBackupHelper(Context context) {
+    public SharedPreferencesBackupHelper(Context context, String[] prefGroups) {
+        super(context);
+
         mContext = context;
+        mPrefGroups = prefGroups;
     }
 
-    public SharedPreferencesBackupHelper(Context context, String keyPrefix) {
-        mContext = context;
-        mKeyPrefix = keyPrefix;
-    }
-    
-    public void performBackup(ParcelFileDescriptor oldSnapshot, ParcelFileDescriptor newSnapshot,
-            BackupDataOutput data, String[] prefGroups) {
+    public void performBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
+            ParcelFileDescriptor newState) {
         Context context = mContext;
         
         // make filenames for the prefGroups
+        String[] prefGroups = mPrefGroups;
         final int N = prefGroups.length;
         String[] files = new String[N];
         for (int i=0; i<N; i++) {
             files[i] = context.getSharedPrefsFile(prefGroups[i]).getAbsolutePath();
         }
 
-        // make keys if necessary
-        String[] keys = FileBackupHelper.makeKeys(mKeyPrefix, prefGroups);
-
         // go
-        FileBackupHelper.performBackup_checked(oldSnapshot, data, newSnapshot, files, prefGroups);
+        performBackup_checked(oldState, data, newState, files, prefGroups);
+    }
+
+    public void restoreEntity(BackupDataInputStream data) {
+        Context context = mContext;
+        
+        // TODO: turn this off before ship
+        Log.d(TAG, "got entity '" + data.getKey() + "' size=" + data.size());
+        String key = data.getKey();
+        if (isKeyInList(key, mPrefGroups)) {
+            File f = context.getSharedPrefsFile(key).getAbsoluteFile();
+            writeFile(f, data);
+        }
     }
 }
 
diff --git a/core/java/android/content/AbstractSyncableContentProvider.java b/core/java/android/content/AbstractSyncableContentProvider.java
index e628dcd..db73dd5 100644
--- a/core/java/android/content/AbstractSyncableContentProvider.java
+++ b/core/java/android/content/AbstractSyncableContentProvider.java
@@ -141,7 +141,8 @@
         public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
             if (!upgradeDatabase(db, oldVersion, newVersion)) {
                 mSyncState.discardSyncData(db, null /* all accounts */);
-                getContext().getContentResolver().startSync(mContentUri, new Bundle());
+                ContentResolver.requestSync(null /* all accounts */,
+                        mContentUri.getAuthority(), new Bundle());
             }
         }
 
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index a01c5d1..98ed098 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -48,9 +48,18 @@
  * This class provides applications access to the content model.
  */
 public abstract class ContentResolver {
-    public final static String SYNC_EXTRAS_ACCOUNT = "account";
+    /**
+     * @deprecated instead use
+     * {@link #requestSync(android.accounts.Account, String, android.os.Bundle)}
+     */
+    public static final String SYNC_EXTRAS_ACCOUNT = "account";
     public static final String SYNC_EXTRAS_EXPEDITED = "expedited";
+    /**
+     * @deprecated instead use
+     * {@link #SYNC_EXTRAS_MANUAL}
+     */
     public static final String SYNC_EXTRAS_FORCE = "force";
+    public static final String SYNC_EXTRAS_MANUAL = "force";
     public static final String SYNC_EXTRAS_UPLOAD = "upload";
     public static final String SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS = "deletions_override";
     public static final String SYNC_EXTRAS_DISCARD_LOCAL_DELETIONS = "discard_deletions";
@@ -90,7 +99,35 @@
      * in the cursor is the same.
      */
     public static final String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir";
-    
+
+    /** @hide */
+    public static final int SYNC_ERROR_SYNC_ALREADY_IN_PROGRESS = 1;
+    /** @hide */
+    public static final int SYNC_ERROR_AUTHENTICATION = 2;
+    /** @hide */
+    public static final int SYNC_ERROR_IO = 3;
+    /** @hide */
+    public static final int SYNC_ERROR_PARSE = 4;
+    /** @hide */
+    public static final int SYNC_ERROR_CONFLICT = 5;
+    /** @hide */
+    public static final int SYNC_ERROR_TOO_MANY_DELETIONS = 6;
+    /** @hide */
+    public static final int SYNC_ERROR_TOO_MANY_RETRIES = 7;
+    /** @hide */
+    public static final int SYNC_ERROR_INTERNAL = 8;
+
+    /** @hide */
+    public static final int SYNC_OBSERVER_TYPE_SETTINGS = 1<<0;
+    /** @hide */
+    public static final int SYNC_OBSERVER_TYPE_PENDING = 1<<1;
+    /** @hide */
+    public static final int SYNC_OBSERVER_TYPE_ACTIVE = 1<<2;
+    /** @hide */
+    public static final int SYNC_OBSERVER_TYPE_STATUS = 1<<3;
+    /** @hide */
+    public static final int SYNC_OBSERVER_TYPE_ALL = 0x7fffffff;
+
     public ContentResolver(Context context) {
         mContext = context;
     }
@@ -829,11 +866,42 @@
      *
      * @param uri the uri of the provider to sync or null to sync all providers.
      * @param extras any extras to pass to the SyncAdapter.
+     * @deprecated instead use
+     * {@link #requestSync(android.accounts.Account, String, android.os.Bundle)}
      */
     public void startSync(Uri uri, Bundle extras) {
+        Account account = null;
+        if (extras != null) {
+            String accountName = extras.getString(SYNC_EXTRAS_ACCOUNT);
+            if (!TextUtils.isEmpty(accountName)) {
+                account = new Account(accountName, "com.google.GAIA");
+            }
+            extras.remove(SYNC_EXTRAS_ACCOUNT);
+        }
+        requestSync(account, uri != null ? uri.getAuthority() : null, extras);
+    }
+
+    /**
+     * Start an asynchronous sync operation. If you want to monitor the progress
+     * of the sync you may register a SyncObserver. Only values of the following
+     * types may be used in the extras bundle:
+     * <ul>
+     * <li>Integer</li>
+     * <li>Long</li>
+     * <li>Boolean</li>
+     * <li>Float</li>
+     * <li>Double</li>
+     * <li>String</li>
+     * </ul>
+     *
+     * @param account which account should be synced
+     * @param authority which authority should be synced
+     * @param extras any extras to pass to the SyncAdapter.
+     */
+    public static void requestSync(Account account, String authority, Bundle extras) {
         validateSyncExtrasBundle(extras);
         try {
-            getContentService().startSync(uri, extras);
+            getContentService().requestSync(account, authority, extras);
         } catch (RemoteException e) {
         }
     }
@@ -874,13 +942,186 @@
         }
     }
 
+    /**
+     * Cancel any active or pending syncs that match the Uri. If the uri is null then
+     * all syncs will be canceled.
+     *
+     * @param uri the uri of the provider to sync or null to sync all providers.
+     * @deprecated instead use {@link #cancelSync(android.accounts.Account, String)}
+     */
     public void cancelSync(Uri uri) {
+        cancelSync(null /* all accounts */, uri != null ? uri.getAuthority() : null);
+    }
+
+    /**
+     * Cancel any active or pending syncs that match account and authority. The account and
+     * authority can each independently be set to null, which means that syncs with any account
+     * or authority, respectively, will match.
+     *
+     * @param account filters the syncs that match by this account
+     * @param authority filters the syncs that match by this authority
+     */
+    public static void cancelSync(Account account, String authority) {
         try {
-            getContentService().cancelSync(uri);
+            getContentService().cancelSync(account, authority);
         } catch (RemoteException e) {
         }
     }
 
+    /**
+     * Get information about the SyncAdapters that are known to the system.
+     * @return an array of SyncAdapters that have registered with the system
+     */
+    public static SyncAdapterType[] getSyncAdapterTypes() {
+        try {
+            return getContentService().getSyncAdapterTypes();
+        } catch (RemoteException e) {
+            throw new RuntimeException("the ContentService should always be reachable", e);
+        }
+    }
+
+    /**
+     * Check if the provider should be synced when a network tickle is received
+     *
+     * @param account the account whose setting we are querying
+     * @param authority the provider whose setting we are querying
+     * @return true if the provider should be synced when a network tickle is received
+     */
+    public static boolean getSyncAutomatically(Account account, String authority) {
+        try {
+            return getContentService().getSyncAutomatically(account, authority);
+        } catch (RemoteException e) {
+            throw new RuntimeException("the ContentService should always be reachable", e);
+        }
+    }
+
+    /**
+     * Set whether or not the provider is synced when it receives a network tickle.
+     *
+     * @param account the account whose setting we are querying
+     * @param authority the provider whose behavior is being controlled
+     * @param sync true if the provider should be synced when tickles are received for it
+     */
+    public static void setSyncAutomatically(Account account, String authority, boolean sync) {
+        try {
+            getContentService().setSyncAutomatically(account, authority, sync);
+        } catch (RemoteException e) {
+            // exception ignored; if this is thrown then it means the runtime is in the midst of
+            // being restarted
+        }
+    }
+
+    /**
+     * Gets the master auto-sync setting that applies to all the providers and accounts.
+     * If this is false then the per-provider auto-sync setting is ignored.
+     *
+     * @return the master auto-sync setting that applies to all the providers and accounts
+     */
+    public static boolean getMasterSyncAutomatically() {
+        try {
+            return getContentService().getMasterSyncAutomatically();
+        } catch (RemoteException e) {
+            throw new RuntimeException("the ContentService should always be reachable", e);
+        }
+    }
+
+    /**
+     * Sets the master auto-sync setting that applies to all the providers and accounts.
+     * If this is false then the per-provider auto-sync setting is ignored.
+     *
+     * @param sync the master auto-sync setting that applies to all the providers and accounts
+     */
+    public static void setMasterSyncAutomatically(boolean sync) {
+        try {
+            getContentService().setMasterSyncAutomatically(sync);
+        } catch (RemoteException e) {
+            // exception ignored; if this is thrown then it means the runtime is in the midst of
+            // being restarted
+        }
+    }
+
+    /**
+     * Returns true if there is currently a sync operation for the given
+     * account or authority in the pending list, or actively being processed.
+     * @param account the account whose setting we are querying
+     * @param authority the provider whose behavior is being queried
+     * @return true if a sync is active for the given account or authority.
+     */
+    public static boolean isSyncActive(Account account, String authority) {
+        try {
+            return getContentService().isSyncActive(account, authority);
+        } catch (RemoteException e) {
+            throw new RuntimeException("the ContentService should always be reachable", e);
+        }
+    }
+
+    /**
+     * If a sync is active returns the information about it, otherwise returns false.
+     * @return the ActiveSyncInfo for the currently active sync or null if one is not active.
+     * @hide
+     */
+    public static ActiveSyncInfo getActiveSync() {
+        try {
+            return getContentService().getActiveSync();
+        } catch (RemoteException e) {
+            throw new RuntimeException("the ContentService should always be reachable", e);
+        }
+    }
+
+    /**
+     * Returns the status that matches the authority. If there are multiples accounts for
+     * the authority, the one with the latest "lastSuccessTime" status is returned.
+     * @param account the account whose setting we are querying
+     * @param authority the provider whose behavior is being queried
+     * @return the SyncStatusInfo for the authority, or null if none exists
+     * @hide
+     */
+    public static SyncStatusInfo getSyncStatus(Account account, String authority) {
+        try {
+            return getContentService().getSyncStatus(account, authority);
+        } catch (RemoteException e) {
+            throw new RuntimeException("the ContentService should always be reachable", e);
+        }
+    }
+
+    /**
+     * Return true if the pending status is true of any matching authorities.
+     * @param account the account whose setting we are querying
+     * @param authority the provider whose behavior is being queried
+     * @return true if there is a pending sync with the matching account and authority
+     */
+    public static boolean isSyncPending(Account account, String authority) {
+        try {
+            return getContentService().isSyncPending(account, authority);
+        } catch (RemoteException e) {
+            throw new RuntimeException("the ContentService should always be reachable", e);
+        }
+    }
+
+    public static Object addStatusChangeListener(int mask, final SyncStatusObserver callback) {
+        try {
+            ISyncStatusObserver.Stub observer = new ISyncStatusObserver.Stub() {
+                public void onStatusChanged(int which) throws RemoteException {
+                    callback.onStatusChanged(which);
+                }
+            };
+            getContentService().addStatusChangeListener(mask, observer);
+            return observer;
+        } catch (RemoteException e) {
+            throw new RuntimeException("the ContentService should always be reachable", e);
+        }
+    }
+
+    public static void removeStatusChangeListener(Object handle) {
+        try {
+            getContentService().removeStatusChangeListener((ISyncStatusObserver.Stub) handle);
+        } catch (RemoteException e) {
+            // exception ignored; if this is thrown then it means the runtime is in the midst of
+            // being restarted
+        }
+    }
+
+
     private final class CursorWrapperInner extends CursorWrapper {
         private IContentProvider mContentProvider;
         public static final String TAG="CursorWrapperInner";
diff --git a/core/java/android/content/ContentService.java b/core/java/android/content/ContentService.java
index c768ffa..7a1ad2b 100644
--- a/core/java/android/content/ContentService.java
+++ b/core/java/android/content/ContentService.java
@@ -161,7 +161,9 @@
             }
             if (syncToNetwork) {
                 SyncManager syncManager = getSyncManager();
-                if (syncManager != null) syncManager.scheduleLocalSync(uri);
+                if (syncManager != null) {
+                    syncManager.scheduleLocalSync(null /* all accounts */, uri.getAuthority());
+                }
             }
         } finally {
             restoreCallingIdentity(identityToken);
@@ -187,14 +189,16 @@
         }
     }
 
-    public void startSync(Uri url, Bundle extras) {
+    public void requestSync(Account account, String authority, Bundle extras) {
         ContentResolver.validateSyncExtrasBundle(extras);
         // This makes it so that future permission checks will be in the context of this
         // process rather than the caller's process. We will restore this before returning.
         long identityToken = clearCallingIdentity();
         try {
             SyncManager syncManager = getSyncManager();
-            if (syncManager != null) syncManager.startSync(url, extras);
+            if (syncManager != null) {
+                syncManager.scheduleSync(account, authority, extras, 0 /* no delay */);
+            }
         } finally {
             restoreCallingIdentity(identityToken);
         }
@@ -202,34 +206,50 @@
 
     /**
      * Clear all scheduled sync operations that match the uri and cancel the active sync
-     * if it matches the uri. If the uri is null, clear all scheduled syncs and cancel
-     * the active one, if there is one.
-     * @param uri Filter on the sync operations to cancel, or all if null.
+     * if they match the authority and account, if they are present.
+     * @param account filter the pending and active syncs to cancel using this account
+     * @param authority filter the pending and active syncs to cancel using this authority
      */
-    public void cancelSync(Uri uri) {
+    public void cancelSync(Account account, String authority) {
         // This makes it so that future permission checks will be in the context of this
         // process rather than the caller's process. We will restore this before returning.
         long identityToken = clearCallingIdentity();
         try {
             SyncManager syncManager = getSyncManager();
             if (syncManager != null) {
-                syncManager.clearScheduledSyncOperations(uri);
-                syncManager.cancelActiveSync(uri);
+                syncManager.clearScheduledSyncOperations(account, authority);
+                syncManager.cancelActiveSync(account, authority);
             }
         } finally {
             restoreCallingIdentity(identityToken);
         }
     }
 
-    public boolean getSyncProviderAutomatically(String providerName) {
+    /**
+     * Get information about the SyncAdapters that are known to the system.
+     * @return an array of SyncAdapters that have registered with the system
+     */
+    public SyncAdapterType[] getSyncAdapterTypes() {
+        // This makes it so that future permission checks will be in the context of this
+        // process rather than the caller's process. We will restore this before returning.
+        long identityToken = clearCallingIdentity();
+        try {
+            SyncManager syncManager = getSyncManager();
+            return syncManager.getSyncAdapterTypes();
+        } finally {
+            restoreCallingIdentity(identityToken);
+        }
+    }
+    
+    public boolean getSyncAutomatically(Account account, String providerName) {
         mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
                 "no permission to read the sync settings");
         long identityToken = clearCallingIdentity();
         try {
             SyncManager syncManager = getSyncManager();
             if (syncManager != null) {
-                return syncManager.getSyncStorageEngine().getSyncProviderAutomatically(
-                        null, providerName);
+                return syncManager.getSyncStorageEngine().getSyncAutomatically(
+                        account, providerName);
             }
         } finally {
             restoreCallingIdentity(identityToken);
@@ -237,29 +257,29 @@
         return false;
     }
 
-    public void setSyncProviderAutomatically(String providerName, boolean sync) {
+    public void setSyncAutomatically(Account account, String providerName, boolean sync) {
         mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
                 "no permission to write the sync settings");
         long identityToken = clearCallingIdentity();
         try {
             SyncManager syncManager = getSyncManager();
             if (syncManager != null) {
-                syncManager.getSyncStorageEngine().setSyncProviderAutomatically(
-                        null, providerName, sync);
+                syncManager.getSyncStorageEngine().setSyncAutomatically(
+                        account, providerName, sync);
             }
         } finally {
             restoreCallingIdentity(identityToken);
         }
     }
 
-    public boolean getListenForNetworkTickles() {
+    public boolean getMasterSyncAutomatically() {
         mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
                 "no permission to read the sync settings");
         long identityToken = clearCallingIdentity();
         try {
             SyncManager syncManager = getSyncManager();
             if (syncManager != null) {
-                return syncManager.getSyncStorageEngine().getListenForNetworkTickles();
+                return syncManager.getSyncStorageEngine().getMasterSyncAutomatically();
             }
         } finally {
             restoreCallingIdentity(identityToken);
@@ -267,14 +287,14 @@
         return false;
     }
     
-    public void setListenForNetworkTickles(boolean flag) {
+    public void setMasterSyncAutomatically(boolean flag) {
         mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
                 "no permission to write the sync settings");
         long identityToken = clearCallingIdentity();
         try {
             SyncManager syncManager = getSyncManager();
             if (syncManager != null) {
-                syncManager.getSyncStorageEngine().setListenForNetworkTickles(flag);
+                syncManager.getSyncStorageEngine().setMasterSyncAutomatically(flag);
             }
         } finally {
             restoreCallingIdentity(identityToken);
@@ -312,7 +332,7 @@
         return null;
     }
     
-    public SyncStatusInfo getStatusByAuthority(String authority) {
+    public SyncStatusInfo getSyncStatus(Account account, String authority) {
         mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
                 "no permission to read the sync stats");
         long identityToken = clearCallingIdentity();
@@ -328,15 +348,14 @@
         return null;
     }
     
-    public boolean isAuthorityPending(Account account, String authority) {
+    public boolean isSyncPending(Account account, String authority) {
         mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS,
                 "no permission to read the sync stats");
         long identityToken = clearCallingIdentity();
         try {
             SyncManager syncManager = getSyncManager();
             if (syncManager != null) {
-                return syncManager.getSyncStorageEngine().isAuthorityPending(
-                        account, authority);
+                return syncManager.getSyncStorageEngine().isSyncPending(account, authority);
             }
         } finally {
             restoreCallingIdentity(identityToken);
@@ -349,8 +368,7 @@
         try {
             SyncManager syncManager = getSyncManager();
             if (syncManager != null) {
-                syncManager.getSyncStorageEngine().addStatusChangeListener(
-                        mask, callback);
+                syncManager.getSyncStorageEngine().addStatusChangeListener(mask, callback);
             }
         } finally {
             restoreCallingIdentity(identityToken);
@@ -362,8 +380,7 @@
         try {
             SyncManager syncManager = getSyncManager();
             if (syncManager != null) {
-                syncManager.getSyncStorageEngine().removeStatusChangeListener(
-                        callback);
+                syncManager.getSyncStorageEngine().removeStatusChangeListener(callback);
             }
         } finally {
             restoreCallingIdentity(identityToken);
diff --git a/core/java/android/content/IContentService.aidl b/core/java/android/content/IContentService.aidl
index 4352227..658a5bc 100644
--- a/core/java/android/content/IContentService.aidl
+++ b/core/java/android/content/IContentService.aidl
@@ -19,6 +19,7 @@
 import android.accounts.Account;
 import android.content.ActiveSyncInfo;
 import android.content.ISyncStatusObserver;
+import android.content.SyncAdapterType;
 import android.content.SyncStatusInfo;
 import android.net.Uri;
 import android.os.Bundle;
@@ -35,15 +36,15 @@
     void notifyChange(in Uri uri, IContentObserver observer,
             boolean observerWantsSelfNotifications, boolean syncToNetwork);
 
-    void startSync(in Uri url, in Bundle extras);
-    void cancelSync(in Uri uri);
+    void requestSync(in Account account, String authority, in Bundle extras);
+    void cancelSync(in Account account, String authority);
     
     /**
      * Check if the provider should be synced when a network tickle is received
      * @param providerName the provider whose setting we are querying
      * @return true of the provider should be synced when a network tickle is received
      */
-    boolean getSyncProviderAutomatically(String providerName);
+    boolean getSyncAutomatically(in Account account, String providerName);
 
     /**
      * Set whether or not the provider is synced when it receives a network tickle.
@@ -51,11 +52,11 @@
      * @param providerName the provider whose behavior is being controlled
      * @param sync true if the provider should be synced when tickles are received for it
      */
-    void setSyncProviderAutomatically(String providerName, boolean sync);
+    void setSyncAutomatically(in Account account, String providerName, boolean sync);
 
-    void setListenForNetworkTickles(boolean flag);
+    void setMasterSyncAutomatically(boolean flag);
 
-    boolean getListenForNetworkTickles();
+    boolean getMasterSyncAutomatically();
     
     /**
      * Returns true if there is currently a sync operation for the given
@@ -66,17 +67,23 @@
     ActiveSyncInfo getActiveSync();
     
     /**
+     * Returns the types of the SyncAdapters that are registered with the system.
+     * @return Returns the types of the SyncAdapters that are registered with the system.
+     */
+    SyncAdapterType[] getSyncAdapterTypes();
+
+    /**
      * Returns the status that matches the authority. If there are multiples accounts for
      * the authority, the one with the latest "lastSuccessTime" status is returned.
      * @param authority the authority whose row should be selected
      * @return the SyncStatusInfo for the authority, or null if none exists
      */
-    SyncStatusInfo getStatusByAuthority(String authority);
+    SyncStatusInfo getSyncStatus(in Account account, String authority);
 
     /**
      * Return true if the pending status is true of any matching authorities.
      */
-    boolean isAuthorityPending(in Account account, String authority);
+    boolean isSyncPending(in Account account, String authority);
     
     void addStatusChangeListener(int mask, ISyncStatusObserver callback);
     
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 33e769e..87f762d 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1593,6 +1593,15 @@
     public static final String ACTION_REMOTE_INTENT =
             "android.intent.action.REMOTE_INTENT";
 
+    /**
+     * @hide
+     * TODO: This will be unhidden in a later CL.
+     * Broadcast Action: The TextToSpeech synthesizer has completed processing 
+     * all of the text in the speech queue.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_TTS_QUEUE_PROCESSING_COMPLETED =
+            "android.intent.action.TTS_QUEUE_PROCESSING_COMPLETED";
 
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
diff --git a/core/java/android/content/SyncAdapterType.aidl b/core/java/android/content/SyncAdapterType.aidl
new file mode 100644
index 0000000..e67841f
--- /dev/null
+++ b/core/java/android/content/SyncAdapterType.aidl
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+package android.content;
+
+parcelable SyncAdapterType;
+
diff --git a/core/java/android/content/SyncAdapterType.java b/core/java/android/content/SyncAdapterType.java
index 368a879..5a96003 100644
--- a/core/java/android/content/SyncAdapterType.java
+++ b/core/java/android/content/SyncAdapterType.java
@@ -17,12 +17,14 @@
 package android.content;
 
 import android.text.TextUtils;
+import android.os.Parcelable;
+import android.os.Parcel;
 
 /**
  * Value type that represents a SyncAdapterType. This object overrides {@link #equals} and
  * {@link #hashCode}, making it suitable for use as the key of a {@link java.util.Map}
  */
-public class SyncAdapterType {
+public class SyncAdapterType implements Parcelable {
     public final String authority;
     public final String accountType;
 
@@ -54,4 +56,27 @@
     public String toString() {
         return "SyncAdapterType {name=" + authority + ", type=" + accountType + "}";
     }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(authority);
+        dest.writeString(accountType);
+    }
+
+    public SyncAdapterType(Parcel source) {
+        this(source.readString(), source.readString());
+    }
+
+    public static final Creator<SyncAdapterType> CREATOR = new Creator<SyncAdapterType>() {
+        public SyncAdapterType createFromParcel(Parcel source) {
+            return new SyncAdapterType(source);
+        }
+
+        public SyncAdapterType[] newArray(int size) {
+            return new SyncAdapterType[size];
+        }
+    };
 }
\ No newline at end of file
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index c7954a5..f73b394 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -35,7 +35,6 @@
 import android.content.pm.RegisteredServicesCache;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
-import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -72,7 +71,7 @@
 import java.util.Map;
 import java.util.PriorityQueue;
 import java.util.Random;
-import java.util.Set;
+import java.util.Collection;
 
 /**
  * @hide
@@ -160,7 +159,7 @@
                             Log.v(TAG, "Internal storage is low.");
                         }
                         mStorageIsLow = true;
-                        cancelActiveSync(null /* no url */);
+                        cancelActiveSync(null /* any account */, null /* any authority */);
                     } else if (Intent.ACTION_DEVICE_STORAGE_OK.equals(action)) {
                         if (Log.isLoggable(TAG, Log.VERBOSE)) {
                             Log.v(TAG, "Internal storage is ok.");
@@ -204,7 +203,7 @@
         if (hadAccountsAlready && accounts.length > 0) {
             // request a sync so that if the password was changed we will
             // retry any sync that failed when it was wrong
-            startSync(null /* all providers */, null /* no extras */);
+            scheduleSync(null, null, null, 0 /* no delay */);
         }
     }
 
@@ -327,7 +326,7 @@
         mHandleAlarmWakeLock.setReferenceCounted(false);
 
         mSyncStorageEngine.addStatusChangeListener(
-                SyncStorageEngine.CHANGE_SETTINGS, new ISyncStatusObserver.Stub() {
+                ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, new ISyncStatusObserver.Stub() {
             public void onStatusChanged(int which) {
                 // force the sync loop to run if the settings change
                 sendCheckAlarmsMessage();
@@ -406,7 +405,8 @@
         scheduleSyncPollAlarm(nextRelativePollTimeMs);
 
         // perform a poll
-        scheduleSync(null /* sync all syncable providers */, new Bundle(), 0 /* no delay */);
+        scheduleSync(null /* sync all syncable accounts */, null /* sync all syncable providers */,
+                new Bundle(), 0 /* no delay */);
     }
 
     private void writeSyncPollTime(long when) {
@@ -502,20 +502,21 @@
      *
      * <p>You'll start getting callbacks after this.
      *
-     * @param url The Uri of a specific provider to be synced, or
-     *          null to sync all providers.
+     * @param requestedAccount the account to sync, may be null to signify all accounts
+     * @param requestedAuthority the authority to sync, may be null to indicate all authorities
      * @param extras a Map of SyncAdapter-specific information to control
 *          syncs of a specific provider. Can be null. Is ignored
 *          if the url is null.
      * @param delay how many milliseconds in the future to wait before performing this
-     *   sync. -1 means to make this the next sync to perform.
      */
-    public void scheduleSync(Uri url, Bundle extras, long delay) {
+    public void scheduleSync(Account requestedAccount, String requestedAuthority,
+            Bundle extras, long delay) {
         boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
         if (isLoggable) {
             Log.v(TAG, "scheduleSync:"
                     + " delay " + delay
-                    + ", url " + ((url == null) ? "(null)" : url)
+                    + ", account " + requestedAccount
+                    + ", authority " + requestedAuthority
                     + ", extras " + ((extras == null) ? "(null)" : extras));
         }
 
@@ -539,9 +540,8 @@
         }
 
         Account[] accounts;
-        Account accountFromExtras = extras.getParcelable(ContentResolver.SYNC_EXTRAS_ACCOUNT);
-        if (accountFromExtras != null) {
-            accounts = new Account[]{accountFromExtras};
+        if (requestedAccount != null) {
+            accounts = new Account[]{requestedAccount};
         } else {
             // if the accounts aren't configured yet then we can't support an account-less
             // sync request
@@ -563,14 +563,14 @@
         }
 
         final boolean uploadOnly = extras.getBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, false);
-        final boolean force = extras.getBoolean(ContentResolver.SYNC_EXTRAS_FORCE, false);
+        final boolean manualSync = extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false);
 
         int source;
         if (uploadOnly) {
             source = SyncStorageEngine.SOURCE_LOCAL;
-        } else if (force) {
+        } else if (manualSync) {
             source = SyncStorageEngine.SOURCE_USER;
-        } else if (url == null) {
+        } else if (requestedAuthority == null) {
             source = SyncStorageEngine.SOURCE_POLL;
         } else {
             // this isn't strictly server, since arbitrary callers can (and do) request
@@ -578,9 +578,9 @@
             source = SyncStorageEngine.SOURCE_SERVER;
         }
 
-        // compile a list of authorities that have sync adapters
-        // for each authority sync each account that matches a sync adapter
-        Set<String> syncableAuthorities = new HashSet<String>();
+        // Compile a list of authorities that have sync adapters.
+        // For each authority sync each account that matches a sync adapter.
+        final HashSet<String> syncableAuthorities = new HashSet<String>();
         for (RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapter :
                 mSyncAdapters.getAllServices()) {
             syncableAuthorities.add(syncAdapter.type.authority);
@@ -588,10 +588,10 @@
 
         // if the url was specified then replace the list of authorities with just this authority
         // or clear it if this authority isn't syncable
-        if (url != null) {
-            boolean isSyncable = syncableAuthorities.contains(url.getAuthority());
+        if (requestedAuthority != null) {
+            final boolean isSyncable = syncableAuthorities.contains(requestedAuthority);
             syncableAuthorities.clear();
-            if (isSyncable) syncableAuthorities.add(url.getAuthority());
+            if (isSyncable) syncableAuthorities.add(requestedAuthority);
         }
 
         for (String authority : syncableAuthorities) {
@@ -614,10 +614,10 @@
         mStatusText = message;
     }
 
-    public void scheduleLocalSync(Uri url) {
+    public void scheduleLocalSync(Account account, String authority) {
         final Bundle extras = new Bundle();
         extras.putBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, true);
-        scheduleSync(url, extras, LOCAL_SYNC_DELAY);
+        scheduleSync(account, authority, extras, LOCAL_SYNC_DELAY);
     }
 
     private IPackageManager getPackageManager() {
@@ -631,18 +631,16 @@
         return mPackageManager;
     }
 
-    /**
-     * Initiate a sync for this given URL, or pass null for a full sync.
-     *
-     * <p>You'll start getting callbacks after this.
-     *
-     * @param url The Uri of a specific provider to be synced, or
-     *          null to sync all providers.
-     * @param extras a Map of SyncAdapter specific information to control
-     *          syncs of a specific provider. Can be null. Is ignored
-     */
-    public void startSync(Uri url, Bundle extras) {
-        scheduleSync(url, extras, 0 /* no delay */);
+    public SyncAdapterType[] getSyncAdapterTypes() {
+        final Collection<RegisteredServicesCache.ServiceInfo<SyncAdapterType>> serviceInfos =
+                mSyncAdapters.getAllServices();
+        SyncAdapterType[] types = new SyncAdapterType[serviceInfos.size()];
+        int i = 0;
+        for (RegisteredServicesCache.ServiceInfo<SyncAdapterType> serviceInfo : serviceInfos) {
+            types[i] = serviceInfo.type;
+            ++i;
+        }
+        return types;
     }
 
     public void updateHeartbeatTime() {
@@ -725,17 +723,22 @@
     }
 
     /**
-     * Cancel the active sync if it matches the uri. The uri corresponds to the one passed
-     * in to startSync().
-     * @param uri If non-null, the active sync is only canceled if it matches the uri.
-     *   If null, any active sync is canceled.
+     * Cancel the active sync if it matches the authority and account.
+     * @param account limit the cancelations to syncs with this account, if non-null
+     * @param authority limit the cancelations to syncs with this authority, if non-null
      */
-    public void cancelActiveSync(Uri uri) {
+    public void cancelActiveSync(Account account, String authority) {
         ActiveSyncContext activeSyncContext = mActiveSyncContext;
         if (activeSyncContext != null) {
-            // if a Uri was specified then only cancel the sync if it matches the the uri
-            if (uri != null) {
-                if (!uri.getAuthority().equals(activeSyncContext.mSyncOperation.authority)) {
+            // if an authority was specified then only cancel the sync if it matches
+            if (account != null) {
+                if (!account.equals(activeSyncContext.mSyncOperation.account)) {
+                    return;
+                }
+            }
+            // if an account was specified then only cancel the sync if it matches
+            if (authority != null) {
+                if (!authority.equals(activeSyncContext.mSyncOperation.authority)) {
                     return;
                 }
             }
@@ -787,14 +790,13 @@
     }
 
     /**
-     * Remove any scheduled sync operations that match uri. The uri corresponds to the one passed
-     * in to startSync().
-     * @param uri If non-null, only operations that match the uri are cleared.
-     *   If null, all operations are cleared.
+     * Remove scheduled sync operations.
+     * @param account limit the removals to operations with this account, if non-null
+     * @param authority limit the removals to operations with this authority, if non-null
      */
-    public void clearScheduledSyncOperations(Uri uri) {
+    public void clearScheduledSyncOperations(Account account, String authority) {
         synchronized (mSyncQueue) {
-            mSyncQueue.clear(null, uri != null ? uri.getAuthority() : null);
+            mSyncQueue.clear(account, authority);
         }
     }
 
@@ -1558,14 +1560,14 @@
             // Otherwise consume SyncOperations from the head of the SyncQueue until one is
             // found that is runnable (not disabled, etc). If that one is ready to run then
             // start it, otherwise just get out.
-            SyncOperation syncOperation;
+            SyncOperation op;
             final ConnectivityManager connManager = (ConnectivityManager)
                     mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
-            final boolean backgroundDataSetting = connManager.getBackgroundDataSetting();
+            final boolean backgroundDataUsageAllowed = connManager.getBackgroundDataSetting();
             synchronized (mSyncQueue) {
                 while (true) {
-                    syncOperation = mSyncQueue.head();
-                    if (syncOperation == null) {
+                    op = mSyncQueue.head();
+                    if (op == null) {
                         if (isLoggable) {
                             Log.v(TAG, "runStateIdle: no more sync operations, returning");
                         }
@@ -1575,39 +1577,40 @@
                     // Sync is disabled, drop this operation.
                     if (!isSyncEnabled()) {
                         if (isLoggable) {
-                            Log.v(TAG, "runStateIdle: sync disabled, dropping " + syncOperation);
+                            Log.v(TAG, "runStateIdle: sync disabled, dropping " + op);
                         }
                         mSyncQueue.popHead();
                         continue;
                     }
 
-                    // skip the sync if it isn't a force and the settings are off for this provider
-                    final boolean force = syncOperation.extras.getBoolean(
-                            ContentResolver.SYNC_EXTRAS_FORCE, false);
-                    if (!force && (!backgroundDataSetting
-                            || !mSyncStorageEngine.getListenForNetworkTickles()
-                            || !mSyncStorageEngine.getSyncProviderAutomatically(
-                                    null, syncOperation.authority))) {
+                    // skip the sync if it isn't manual and auto sync is disabled
+                    final boolean manualSync = op.extras.getBoolean(
+                            ContentResolver.SYNC_EXTRAS_MANUAL, false);
+                    final boolean syncAutomatically =
+                            mSyncStorageEngine.getSyncAutomatically(op.account, op.authority)
+                                    || mSyncStorageEngine.getMasterSyncAutomatically();
+                    boolean syncAllowed =
+                            manualSync || (backgroundDataUsageAllowed && syncAutomatically);
+                    if (!syncAllowed) {
                         if (isLoggable) {
-                            Log.v(TAG, "runStateIdle: sync off, dropping " + syncOperation);
+                            Log.v(TAG, "runStateIdle: sync off, dropping " + op);
                         }
                         mSyncQueue.popHead();
                         continue;
                     }
 
                     // skip the sync if the account of this operation no longer exists
-                    if (!ArrayUtils.contains(accounts, syncOperation.account)) {
+                    if (!ArrayUtils.contains(accounts, op.account)) {
                         mSyncQueue.popHead();
                         if (isLoggable) {
-                            Log.v(TAG, "runStateIdle: account not present, dropping "
-                                    + syncOperation);
+                            Log.v(TAG, "runStateIdle: account not present, dropping " + op);
                         }
                         continue;
                     }
 
                     // go ahead and try to sync this syncOperation
                     if (isLoggable) {
-                        Log.v(TAG, "runStateIdle: found sync candidate: " + syncOperation);
+                        Log.v(TAG, "runStateIdle: found sync candidate: " + op);
                     }
                     break;
                 }
@@ -1615,11 +1618,10 @@
                 // If the first SyncOperation isn't ready to run schedule a wakeup and
                 // get out.
                 final long now = SystemClock.elapsedRealtime();
-                if (syncOperation.earliestRunTime > now) {
+                if (op.earliestRunTime > now) {
                     if (Log.isLoggable(TAG, Log.DEBUG)) {
                         Log.d(TAG, "runStateIdle: the time is " + now + " yet the next "
-                                + "sync operation is for " + syncOperation.earliestRunTime
-                                + ": " + syncOperation);
+                                + "sync operation is for " + op.earliestRunTime + ": " + op);
                     }
                     return;
                 }
@@ -1627,14 +1629,14 @@
                 // We will do this sync. Remove it from the queue and run it outside of the
                 // synchronized block.
                 if (isLoggable) {
-                    Log.v(TAG, "runStateIdle: we are going to sync " + syncOperation);
+                    Log.v(TAG, "runStateIdle: we are going to sync " + op);
                 }
                 mSyncQueue.popHead();
             }
 
             // connect to the sync adapter
-            SyncAdapterType syncAdapterType = new SyncAdapterType(syncOperation.authority,
-                    syncOperation.account.mType);
+            SyncAdapterType syncAdapterType = new SyncAdapterType(op.authority,
+                    op.account.mType);
             RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo =
                     mSyncAdapters.getServiceInfo(syncAdapterType);
             if (syncAdapterInfo == null) {
@@ -1646,7 +1648,7 @@
             }
 
             ActiveSyncContext activeSyncContext =
-                    new ActiveSyncContext(syncOperation, insertStartSyncEvent(syncOperation));
+                    new ActiveSyncContext(op, insertStartSyncEvent(op));
             mActiveSyncContext = activeSyncContext;
             if (Log.isLoggable(TAG, Log.VERBOSE)) {
                 Log.v(TAG, "runStateIdle: setting mActiveSyncContext to " + mActiveSyncContext);
@@ -1776,21 +1778,21 @@
          */
         private int syncResultToErrorNumber(SyncResult syncResult) {
             if (syncResult.syncAlreadyInProgress)
-                return SyncStorageEngine.ERROR_SYNC_ALREADY_IN_PROGRESS;
+                return ContentResolver.SYNC_ERROR_SYNC_ALREADY_IN_PROGRESS;
             if (syncResult.stats.numAuthExceptions > 0)
-                return SyncStorageEngine.ERROR_AUTHENTICATION;
+                return ContentResolver.SYNC_ERROR_AUTHENTICATION;
             if (syncResult.stats.numIoExceptions > 0)
-                return SyncStorageEngine.ERROR_IO;
+                return ContentResolver.SYNC_ERROR_IO;
             if (syncResult.stats.numParseExceptions > 0)
-                return SyncStorageEngine.ERROR_PARSE;
+                return ContentResolver.SYNC_ERROR_PARSE;
             if (syncResult.stats.numConflictDetectedExceptions > 0)
-                return SyncStorageEngine.ERROR_CONFLICT;
+                return ContentResolver.SYNC_ERROR_CONFLICT;
             if (syncResult.tooManyDeletions)
-                return SyncStorageEngine.ERROR_TOO_MANY_DELETIONS;
+                return ContentResolver.SYNC_ERROR_TOO_MANY_DELETIONS;
             if (syncResult.tooManyRetries)
-                return SyncStorageEngine.ERROR_TOO_MANY_RETRIES;
+                return ContentResolver.SYNC_ERROR_TOO_MANY_RETRIES;
             if (syncResult.databaseError)
-                return SyncStorageEngine.ERROR_INTERNAL;
+                return ContentResolver.SYNC_ERROR_INTERNAL;
             throw new IllegalStateException("we are not in an error state, " + syncResult);
         }
 
@@ -1831,9 +1833,10 @@
                 } else {
                     final boolean timeToShowNotification =
                             now > mSyncNotificationInfo.startTime + SYNC_NOTIFICATION_DELAY;
-                    final boolean syncIsForced = syncOperation.extras
-                            .getBoolean(ContentResolver.SYNC_EXTRAS_FORCE, false);
-                    shouldInstall = timeToShowNotification || syncIsForced;
+                    // show the notification immediately if this is a manual sync
+                    final boolean manualSync = syncOperation.extras
+                            .getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false);
+                    shouldInstall = timeToShowNotification || manualSync;
                 }
             }
 
@@ -2088,9 +2091,9 @@
             SyncOperation existingOperation = mOpsByKey.get(operationKey);
 
             // if this operation matches an existing operation that is being retried (delay > 0)
-            // and this operation isn't forced, ignore this operation
+            // and this isn't a manual sync operation, ignore this operation
             if (existingOperation != null && existingOperation.delay > 0) {
-                if (!operation.extras.getBoolean(ContentResolver.SYNC_EXTRAS_FORCE, false)) {
+                if (!operation.extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false)) {
                     return false;
                 }
             }
diff --git a/core/java/android/content/SyncStatusObserver.java b/core/java/android/content/SyncStatusObserver.java
new file mode 100644
index 0000000..663378a
--- /dev/null
+++ b/core/java/android/content/SyncStatusObserver.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+package android.content;
+
+public interface SyncStatusObserver {
+    void onStatusChanged(int which);
+}
diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java
index aaa763d..aaba7c7 100644
--- a/core/java/android/content/SyncStorageEngine.java
+++ b/core/java/android/content/SyncStorageEngine.java
@@ -49,8 +49,6 @@
 import java.util.Iterator;
 import java.util.TimeZone;
 
-import com.google.android.collect.Sets;
-
 /**
  * Singleton that tracks the sync data and overall sync
  * history on the device.
@@ -89,6 +87,9 @@
     /** Enum value for a user-initiated sync. */
     public static final int SOURCE_USER = 3;
 
+    private static final Intent SYNC_CONNECTION_SETTING_CHANGED_INTENT =
+            new Intent("com.android.sync.SYNC_CONN_STATUS_CHANGED");
+
     // TODO: i18n -- grab these out of resources.
     /** String names for the sync source types. */
     public static final String[] SOURCES = { "SERVER",
@@ -96,26 +97,10 @@
                                              "POLL",
                                              "USER" };
 
-    // Error types
-    public static final int ERROR_SYNC_ALREADY_IN_PROGRESS = 1;
-    public static final int ERROR_AUTHENTICATION = 2;
-    public static final int ERROR_IO = 3;
-    public static final int ERROR_PARSE = 4;
-    public static final int ERROR_CONFLICT = 5;
-    public static final int ERROR_TOO_MANY_DELETIONS = 6;
-    public static final int ERROR_TOO_MANY_RETRIES = 7;
-    public static final int ERROR_INTERNAL = 8;
-
     // The MESG column will contain one of these or one of the Error types.
     public static final String MESG_SUCCESS = "success";
     public static final String MESG_CANCELED = "canceled";
 
-    public static final int CHANGE_SETTINGS = 1<<0;
-    public static final int CHANGE_PENDING = 1<<1;
-    public static final int CHANGE_ACTIVE = 1<<2;
-    public static final int CHANGE_STATUS = 1<<3;
-    public static final int CHANGE_ALL = 0x7fffffff;
-    
     public static final int MAX_HISTORY = 15;
     
     private static final int MSG_WRITE_STATUS = 1;
@@ -166,7 +151,7 @@
         final String authority;
         final int ident;
         boolean enabled;
-        
+
         AuthorityInfo(Account account, String authority, int ident) {
             this.account = account;
             this.authority = authority;
@@ -259,7 +244,7 @@
     private int mNumPendingFinished = 0;
     
     private int mNextHistoryId = 0;
-    private boolean mListenForTickles = true;
+    private boolean mMasterSyncAutomatically = true;
     
     private SyncStorageEngine(Context context) {
         mContext = context;
@@ -356,14 +341,14 @@
         }
     }
     
-    public boolean getSyncProviderAutomatically(Account account, String providerName) {
+    public boolean getSyncAutomatically(Account account, String providerName) {
         synchronized (mAuthorities) {
             if (account != null) {
                 AuthorityInfo authority = getAuthorityLocked(account, providerName,
-                        "getSyncProviderAutomatically");
-                return authority != null ? authority.enabled : false;
+                        "getSyncAutomatically");
+                return authority != null && authority.enabled;
             }
-            
+
             int i = mAuthorities.size();
             while (i > 0) {
                 i--;
@@ -377,42 +362,31 @@
         }
     }
 
-    public void setSyncProviderAutomatically(Account account, String providerName,
-            boolean sync) {
+    public void setSyncAutomatically(Account account, String providerName, boolean sync) {
         synchronized (mAuthorities) {
-            if (account != null) {
-                AuthorityInfo authority = getAuthorityLocked(account, providerName,
-                        "setSyncProviderAutomatically");
-                if (authority != null) {
-                    authority.enabled = sync;
-                }
-            } else {
-                int i = mAuthorities.size();
-                while (i > 0) {
-                    i--;
-                    AuthorityInfo authority = mAuthorities.get(i);
-                    if (authority.authority.equals(providerName)) {
-                        authority.enabled = sync;
-                    }
-                }
+            AuthorityInfo authority = getAuthorityLocked(account, providerName,
+                    "setSyncAutomatically");
+            if (authority != null) {
+                authority.enabled = sync;
             }
             writeAccountInfoLocked();
         }
         
-        reportChange(CHANGE_SETTINGS);
+        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
     }
 
-    public void setListenForNetworkTickles(boolean flag) {
+    public void setMasterSyncAutomatically(boolean flag) {
         synchronized (mAuthorities) {
-            mListenForTickles = flag;
+            mMasterSyncAutomatically = flag;
             writeAccountInfoLocked();
         }
-        reportChange(CHANGE_SETTINGS);
+        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS);
+        mContext.sendBroadcast(SYNC_CONNECTION_SETTING_CHANGED_INTENT);
     }
 
-    public boolean getListenForNetworkTickles() {
+    public boolean getMasterSyncAutomatically() {
         synchronized (mAuthorities) {
-            return mListenForTickles;
+            return mMasterSyncAutomatically;
         }
     }
     
@@ -481,7 +455,7 @@
             status.pending = true;
         }
         
-        reportChange(CHANGE_PENDING);
+        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_PENDING);
         return op;
     }
 
@@ -527,7 +501,7 @@
             }
         }
         
-        reportChange(CHANGE_PENDING);
+        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_PENDING);
         return res;
     }
 
@@ -543,7 +517,7 @@
             }
             writePendingOperationsLocked();
         }
-        reportChange(CHANGE_PENDING);
+        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_PENDING);
         return num;
     }
 
@@ -650,14 +624,14 @@
             }
         }
         
-        reportChange(CHANGE_ACTIVE);
+        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE);
     }
 
     /**
      * To allow others to send active change reports, to poke clients.
      */
     public void reportActiveChange() {
-        reportChange(CHANGE_ACTIVE);
+        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_ACTIVE);
     }
     
     /**
@@ -689,7 +663,7 @@
             if (DEBUG) Log.v(TAG, "returning historyId " + id);
         }
         
-        reportChange(CHANGE_STATUS);
+        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_STATUS);
         return id;
     }
 
@@ -793,7 +767,7 @@
             }            
         }
         
-        reportChange(CHANGE_STATUS);
+        reportChange(ContentResolver.SYNC_OBSERVER_TYPE_STATUS);
     }
 
     /**
@@ -851,7 +825,7 @@
     /**
      * Return true if the pending status is true of any matching authorities.
      */
-    public boolean isAuthorityPending(Account account, String authority) {
+    public boolean isSyncPending(Account account, String authority) {
         synchronized (mAuthorities) {
             final int N = mSyncStatus.size();
             for (int i=0; i<N; i++) {
@@ -907,7 +881,7 @@
      */
     public long getInitialSyncFailureTime() {
         synchronized (mAuthorities) {
-            if (!mListenForTickles) {
+            if (!mMasterSyncAutomatically) {
                 return 0;
             }
             
@@ -1041,7 +1015,7 @@
             if ("accounts".equals(tagName)) {
                 String listen = parser.getAttributeValue(
                         null, "listen-for-tickles");
-                mListenForTickles = listen == null
+                mMasterSyncAutomatically = listen == null
                             || Boolean.parseBoolean(listen);
                 eventType = parser.next();
                 do {
@@ -1122,7 +1096,7 @@
             out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
             
             out.startTag(null, "accounts");
-            if (!mListenForTickles) {
+            if (!mMasterSyncAutomatically) {
                 out.attribute(null, "listen-for-tickles", "false");
             }
             
@@ -1262,13 +1236,18 @@
                 String value = c.getString(c.getColumnIndex("value"));
                 if (name == null) continue;
                 if (name.equals("listen_for_tickles")) {
-                    setListenForNetworkTickles(value == null
-                            || Boolean.parseBoolean(value));
+                    setMasterSyncAutomatically(value == null || Boolean.parseBoolean(value));
                 } else if (name.startsWith("sync_provider_")) {
                     String provider = name.substring("sync_provider_".length(),
                             name.length());
-                    setSyncProviderAutomatically(null, provider,
-                            value == null || Boolean.parseBoolean(value));
+                    int i = mAuthorities.size();
+                    while (i > 0) {
+                        i--;
+                        AuthorityInfo authority = mAuthorities.get(i);
+                        if (authority.authority.equals(provider)) {
+                            authority.enabled = value == null || Boolean.parseBoolean(value);
+                        }
+                    }
                 }
             }
             
diff --git a/core/java/android/content/TempProviderSyncAdapter.java b/core/java/android/content/TempProviderSyncAdapter.java
index 0cbe01e..fb05fe7 100644
--- a/core/java/android/content/TempProviderSyncAdapter.java
+++ b/core/java/android/content/TempProviderSyncAdapter.java
@@ -63,12 +63,10 @@
      *
      * @param context allows you to publish status and interact with the
      * @param account the account to sync
-     * @param forced if true then the sync was forced
+     * @param manualSync true if this sync was requested manually by the user
      * @param result information to track what happened during this sync attempt
-     * @return true, if the sync was successfully started. One reason it can
-     *   fail to start is if there is no user configured on the device.
      */
-    public abstract void onSyncStarting(SyncContext context, Account account, boolean forced,
+    public abstract void onSyncStarting(SyncContext context, Account account, boolean manualSync,
             SyncResult result);
 
     /**
@@ -229,12 +227,12 @@
             mAdapterSyncStarted = false;
             String message = null;
 
-            boolean syncForced = extras.getBoolean(ContentResolver.SYNC_EXTRAS_FORCE, false);
+            boolean manualSync = extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false);
 
             try {
                 mProvider.onSyncStart(syncContext, account);
                 mProviderSyncStarted = true;
-                onSyncStarting(syncContext, account, syncForced, mResult);
+                onSyncStarting(syncContext, account, manualSync, mResult);
                 if (mResult.hasError()) {
                     message = "SyncAdapter failed while trying to start sync";
                     return;
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index 680fef8..179b9bd 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -17,8 +17,15 @@
 package android.content.res;
 
 import android.content.pm.ApplicationInfo;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.Region;
 import android.util.DisplayMetrics;
+import android.util.Log;
 import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
 
 /**
  * CompatibilityInfo class keeps the information about compatibility mode that the application is
@@ -27,6 +34,9 @@
  *  {@hide} 
  */
 public class CompatibilityInfo {
+    private static final boolean DBG = false;
+    private static final String TAG = "CompatibilityInfo";
+    
     /** default compatibility info object for compatible applications */
     public static final CompatibilityInfo DEFAULT_COMPATIBILITY_INFO = new CompatibilityInfo(); 
 
@@ -41,36 +51,75 @@
     public static final int DEFAULT_PORTRAIT_HEIGHT = 480;
 
     /**
+     * The x-shift mode that controls the position of the content or the window under
+     * compatibility mode.
+     * {@see getTranslator}
+     * {@see Translator#mShiftMode}
+     */
+    private static final int X_SHIFT_NONE = 0;
+    private static final int X_SHIFT_CONTENT = 1;
+    private static final int X_SHIFT_AND_CLIP_CONTENT = 2;
+    private static final int X_SHIFT_WINDOW = 3;
+
+
+    /**
+     *  A compatibility flags
+     */
+    private int compatibilityFlags;
+    
+    /**
+     * A flag mask to tell if the application needs scaling (when mApplicationScale != 1.0f)
+     * {@see compatibilityFlag}
+     */
+    private static final int SCALING_REQUIRED = 1; 
+
+    /**
+     * A flag mask to indicates that the application can expand over the original size.
+     * The flag is set to true if
+     * 1) Application declares its expandable in manifest file using <expandable /> or
+     * 2) The screen size is same as (320 x 480) * density. 
+     * {@see compatibilityFlag}
+     */
+    private static final int EXPANDABLE = 2;
+    
+    /**
+     * A flag mask to tell if the application is configured to be expandable. This differs
+     * from EXPANDABLE in that the application that is not expandable will be 
+     * marked as expandable if it runs in (320x 480) * density screen size.
+     */
+    private static final int CONFIGURED_EXPANDABLE = 4; 
+
+    private static final int SCALING_EXPANDABLE_MASK = SCALING_REQUIRED | EXPANDABLE;
+
+    /**
      * Application's scale.
      */
-    public final float mApplicationScale;
+    public final float applicationScale;
 
     /**
      * Application's inverted scale.
      */
-    public final float mApplicationInvertedScale;
-    
-    /**
-     * A boolean flag to indicates that the application can expand over the original size.
-     * The flag is set to true if
-     * 1) Application declares its expandable in manifest file using <expandable /> or
-     * 2) The screen size is same as (320 x 480) * density. 
-     */
-    public boolean mExpandable;
+    public final float applicationInvertedScale;
+
 
     /**
-     * A expandable flag in the configuration.
+     * Window size in Compatibility Mode, in real pixels. This is updated by
+     * {@link DisplayMetrics#updateMetrics}.
      */
-    public final boolean mConfiguredExpandable;
+    private int mWidth;
+    private int mHeight;
     
     /**
-     * A boolean flag to tell if the application needs scaling (when mApplicationScale != 1.0f)
+     * The x offset to center the window content. In X_SHIFT_WINDOW mode, the offset is added
+     * to the window's layout. In X_SHIFT_CONTENT/X_SHIFT_AND_CLIP_CONTENT mode, the offset
+     * is used to translate the Canvas.
      */
-    public final boolean mScalingRequired;
+    private int mXOffset;
 
     public CompatibilityInfo(ApplicationInfo appInfo) {
-        mExpandable = mConfiguredExpandable =
-            (appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0;
+        if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
+            compatibilityFlags = EXPANDABLE | CONFIGURED_EXPANDABLE;
+        }
         
         float packageDensityScale = -1.0f;
         if (appInfo.supportsDensities != null) {
@@ -93,23 +142,323 @@
             }
         }
         if (packageDensityScale > 0.0f) {
-            mApplicationScale = packageDensityScale;
+            applicationScale = packageDensityScale;
         } else {
-            mApplicationScale = DisplayMetrics.DEVICE_DENSITY / (float) DisplayMetrics.DEFAULT_DENSITY;
+            applicationScale =
+                    DisplayMetrics.DEVICE_DENSITY / (float) DisplayMetrics.DEFAULT_DENSITY;
         }
-        mApplicationInvertedScale = 1.0f / mApplicationScale;
-        mScalingRequired = mApplicationScale != 1.0f;
+        applicationInvertedScale = 1.0f / applicationScale;
+        if (applicationScale != 1.0f) {
+            compatibilityFlags |= SCALING_REQUIRED;
+        }
     }
 
     private CompatibilityInfo() {
-        mApplicationScale = mApplicationInvertedScale = 1.0f;
-        mExpandable = mConfiguredExpandable = true;
-        mScalingRequired = false;
+        applicationScale = applicationInvertedScale = 1.0f;
+        compatibilityFlags = EXPANDABLE | CONFIGURED_EXPANDABLE;
     }
 
+    /**
+     * Sets the application's visible rect in compatibility mode.
+     * @param xOffset the application's x offset that is added to center the content.
+     * @param widthPixels the application's width in real pixels on the screen.
+     * @param heightPixels the application's height in real pixels on the screen.
+     */
+    public void setVisibleRect(int xOffset, int widthPixels, int heightPixels) {
+        this.mXOffset = xOffset; 
+        mWidth = widthPixels;
+        mHeight = heightPixels;
+    }
+    
+    /**
+     * Sets expandable bit in the compatibility flag.
+     */
+    public void setExpandable(boolean expandable) {
+        if (expandable) {
+            compatibilityFlags |= CompatibilityInfo.EXPANDABLE;
+        } else {
+            compatibilityFlags &= ~CompatibilityInfo.EXPANDABLE;
+        }
+    }
+
+    /**
+     * @return true if the application is configured to be expandable.
+     */
+    public boolean isConfiguredExpandable() {
+        return (compatibilityFlags & CompatibilityInfo.CONFIGURED_EXPANDABLE) != 0;
+    }
+
+    /**
+     * @return true if the scaling is required
+     */
+    public boolean isScalingRequired() {
+        return (compatibilityFlags & SCALING_REQUIRED) != 0;
+    }
+    
     @Override
     public String toString() {
-        return "CompatibilityInfo{scale=" + mApplicationScale +
-                ", expandable=" + mExpandable + "}"; 
+        return "CompatibilityInfo{scale=" + applicationScale +
+                ", compatibility flag=" + compatibilityFlags + "}"; 
     }
-}
+
+    /**
+     * Returns the translator which can translate the coordinates of the window.
+     * There are five different types of Translator.
+     * 
+     * 1) {@link CompatibilityInfo#X_SHIFT_AND_CLIP_CONTENT}
+     *   Shift and clip the content of the window at drawing time. Used for activities'
+     *   main window (with no gravity).
+     * 2) {@link CompatibilityInfo#X_SHIFT_CONTENT}
+     *   Shift the content of the window at drawing time. Used for windows that is created by
+     *   an application and expected to be aligned with the application window.
+     * 3) {@link CompatibilityInfo#X_SHIFT_WINDOW}
+     *   Create the window with adjusted x- coordinates. This is typically used 
+     *   in popup window, where it has to be placed relative to main window.
+     * 4) {@link CompatibilityInfo#X_SHIFT_NONE}
+     *   No adjustment required, such as dialog.
+     * 5) Same as X_SHIFT_WINDOW, but no scaling. This is used by {@link SurfaceView}, which
+     *  does not require scaling, but its window's location has to be adjusted.
+     * 
+     * @param params the window's parameter
+     */
+    public Translator getTranslator(WindowManager.LayoutParams params) {
+        if ( (compatibilityFlags & CompatibilityInfo.SCALING_EXPANDABLE_MASK)
+                == CompatibilityInfo.EXPANDABLE) {
+            if (DBG) Log.d(TAG, "no translation required");
+            return null;
+        }
+        
+        if ((compatibilityFlags & CompatibilityInfo.EXPANDABLE) == 0) {
+            if ((params.flags & WindowManager.LayoutParams.FLAG_NO_COMPATIBILITY_SCALING) != 0) {
+                if (DBG) Log.d(TAG, "translation for surface view selected");
+                return new Translator(X_SHIFT_WINDOW, false, 1.0f, 1.0f);
+            } else {
+                int shiftMode;
+                if (params.gravity == Gravity.NO_GRAVITY) {
+                    // For Regular Application window
+                    shiftMode = X_SHIFT_AND_CLIP_CONTENT;
+                    if (DBG) Log.d(TAG, "shift and clip translator");
+                } else if (params.width == WindowManager.LayoutParams.FILL_PARENT) {
+                    // For Regular Application window
+                    shiftMode = X_SHIFT_CONTENT;
+                    if (DBG) Log.d(TAG, "shift content translator");
+                } else if ((params.gravity & Gravity.LEFT) != 0 && params.x > 0) {
+                    shiftMode = X_SHIFT_WINDOW;
+                    if (DBG) Log.d(TAG, "shift window translator");
+                } else {
+                    shiftMode = X_SHIFT_NONE;
+                    if (DBG) Log.d(TAG, "no content/window translator");
+                }
+                return new Translator(shiftMode);
+            }
+        } else if (isScalingRequired()) {
+            return new Translator();
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * A helper object to translate the screen and window coordinates back and forth.
+     * @hide
+     */
+    public class Translator {
+        final private int mShiftMode;
+        final public boolean scalingRequired;
+        final public float applicationScale;
+        final public float applicationInvertedScale;
+        
+        private Rect mContentInsetsBuffer = null;
+        private Rect mVisibleInsets = null;
+        
+        Translator(int shiftMode, boolean scalingRequired, float applicationScale,
+                float applicationInvertedScale) {
+            mShiftMode = shiftMode;
+            this.scalingRequired = scalingRequired;
+            this.applicationScale = applicationScale;
+            this.applicationInvertedScale = applicationInvertedScale;
+        }
+
+        Translator(int shiftMode) {
+            this(shiftMode,
+                    isScalingRequired(),
+                    CompatibilityInfo.this.applicationScale,
+                    CompatibilityInfo.this.applicationInvertedScale);
+        }
+        
+        Translator() {
+            this(X_SHIFT_NONE);
+        }
+
+        /**
+         * Translate the screen rect to the application frame.
+         */
+        public void translateRectInScreenToAppWinFrame(Rect rect) {
+            if (rect.isEmpty()) return; // skip if the window size is empty.
+            switch (mShiftMode) {
+                case X_SHIFT_AND_CLIP_CONTENT:
+                    rect.intersect(0, 0, mWidth, mHeight);
+                    break;
+                case X_SHIFT_CONTENT:
+                    rect.intersect(0, 0, mWidth + mXOffset, mHeight);
+                    break;
+                case X_SHIFT_WINDOW:
+                case X_SHIFT_NONE:
+                    break;
+            }
+            if (scalingRequired) {
+                rect.scale(applicationInvertedScale);
+            }
+        }
+
+        /**
+         * Translate the region in window to screen. 
+         */
+        public void translateRegionInWindowToScreen(Region transparentRegion) {
+            switch (mShiftMode) {
+                case X_SHIFT_AND_CLIP_CONTENT:
+                case X_SHIFT_CONTENT:
+                    transparentRegion.scale(applicationScale);
+                    transparentRegion.translate(mXOffset, 0);
+                    break;
+                case X_SHIFT_WINDOW:
+                case X_SHIFT_NONE:
+                    transparentRegion.scale(applicationScale);
+            }
+        }
+
+        /**
+         * Apply translation to the canvas that is necessary to draw the content.
+         */
+        public void translateCanvas(Canvas canvas) {
+            if (mShiftMode == X_SHIFT_CONTENT ||
+                    mShiftMode == X_SHIFT_AND_CLIP_CONTENT) {
+                // TODO: clear outside when rotation is changed.
+
+                // Translate x-offset only when the content is shifted.
+                canvas.translate(mXOffset, 0);
+            }
+            if (scalingRequired) {
+                canvas.scale(applicationScale, applicationScale);
+            }
+        }
+
+        /**
+         * Translate the motion event captured on screen to the application's window.
+         */
+        public void translateEventInScreenToAppWindow(MotionEvent event) {
+            if (mShiftMode == X_SHIFT_CONTENT ||
+                    mShiftMode == X_SHIFT_AND_CLIP_CONTENT) {
+                event.translate(-mXOffset, 0);
+            }
+            if (scalingRequired) {
+                event.scale(applicationInvertedScale);
+            }
+        }
+
+        /**
+         * Translate the window's layout parameter, from application's view to
+         * Screen's view.
+         */
+        public void translateWindowLayout(WindowManager.LayoutParams params) {
+            switch (mShiftMode) {
+                case X_SHIFT_NONE:
+                case X_SHIFT_AND_CLIP_CONTENT:
+                case X_SHIFT_CONTENT:
+                    params.scale(applicationScale);
+                    break;
+                case X_SHIFT_WINDOW:
+                    params.scale(applicationScale);
+                    params.x += mXOffset;
+                    break;
+            }
+        }
+        
+        /**
+         * Translate a Rect in application's window to screen.
+         */
+        public void translateRectInAppWindowToScreen(Rect rect) {
+            // TODO Auto-generated method stub
+            if (scalingRequired) {
+                rect.scale(applicationScale);
+            }
+            switch(mShiftMode) {
+                case X_SHIFT_NONE:
+                case X_SHIFT_WINDOW:
+                    break;
+                case X_SHIFT_CONTENT:
+                case X_SHIFT_AND_CLIP_CONTENT:
+                    rect.offset(mXOffset, 0);
+                    break;
+            }
+        }
+ 
+        /**
+         * Translate a Rect in screen coordinates into the app window's coordinates.
+         */
+        public void translateRectInScreenToAppWindow(Rect rect) {
+            switch (mShiftMode) {
+                case X_SHIFT_NONE:
+                case X_SHIFT_WINDOW:
+                    break;
+                case X_SHIFT_CONTENT: {
+                    rect.intersects(mXOffset, 0, rect.right, rect.bottom);
+                    int dx = Math.min(mXOffset, rect.left);
+                    rect.offset(-dx, 0);
+                    break;
+                }
+                case X_SHIFT_AND_CLIP_CONTENT: {
+                    rect.intersects(mXOffset, 0, mWidth + mXOffset, mHeight);
+                    int dx = Math.min(mXOffset, rect.left);
+                    rect.offset(-dx, 0);
+                    break;
+                }
+            }
+            if (scalingRequired) {
+                rect.scale(applicationInvertedScale);
+            }
+        }
+
+        /**
+         * Translate the location of the sub window.
+         * @param params
+         */
+        public void translateLayoutParamsInAppWindowToScreen(LayoutParams params) {
+            if (scalingRequired) {
+                params.scale(applicationScale);
+            }
+            switch (mShiftMode) {
+                // the window location on these mode does not require adjustmenet.
+                case X_SHIFT_NONE:
+                case X_SHIFT_WINDOW:
+                    break;
+                case X_SHIFT_CONTENT:
+                case X_SHIFT_AND_CLIP_CONTENT:
+                    params.x += mXOffset;
+                    break;
+            }
+        }
+
+        /**
+         * Translate the content insets in application window to Screen. This uses
+         * the internal buffer for content insets to avoid extra object allocation.
+         */
+        public Rect getTranslatedContentInsets(Rect contentInsets) {
+            if (mContentInsetsBuffer == null) mContentInsetsBuffer = new Rect();
+            mContentInsetsBuffer.set(contentInsets);
+            translateRectInAppWindowToScreen(mContentInsetsBuffer);
+            return mContentInsetsBuffer;
+        }
+
+        /**
+         * Translate the visible insets in application window to Screen. This uses
+         * the internal buffer for content insets to avoid extra object allocation.
+         */
+        public Rect getTranslatedVisbileInsets(Rect visibleInsets) {
+            if (mVisibleInsets == null) mVisibleInsets = new Rect();
+            mVisibleInsets.set(visibleInsets);
+            translateRectInAppWindowToScreen(mVisibleInsets);
+            return mVisibleInsets;
+        }
+    }
+}
\ No newline at end of file
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 71dbd38..cb9d46e 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -158,10 +158,10 @@
         }
         updateConfiguration(config, metrics);
         assets.ensureStringBlocks();
-        if (!mCompatibilityInfo.mScalingRequired) {
-            mPreloadedDrawables = sPreloadedDrawables;
-        } else {
+        if (mCompatibilityInfo.isScalingRequired()) {
             mPreloadedDrawables = emptySparseArray();
+        } else {
+            mPreloadedDrawables = sPreloadedDrawables;
         }
     }
 
diff --git a/core/java/android/database/BulkCursorToCursorAdaptor.java b/core/java/android/database/BulkCursorToCursorAdaptor.java
index c26810a..cf30dd9 100644
--- a/core/java/android/database/BulkCursorToCursorAdaptor.java
+++ b/core/java/android/database/BulkCursorToCursorAdaptor.java
@@ -247,9 +247,11 @@
         try {
             return mBulkCursor.respond(extras);
         } catch (RemoteException e) {
-            // This should never happen because the system kills processes that are using remote
-            // cursors when the provider process is killed.
-            throw new RuntimeException(e);
+            // the system kills processes that are using remote cursors when the provider process
+            // is killed, but this can still happen if this is being called from the system process,
+            // so, better to log and return an empty bundle.
+            Log.w(TAG, "respond() threw RemoteException, returning an empty bundle.", e);
+            return Bundle.EMPTY;
         }
     }
 }
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index d9612af..b0fc78e 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -21,6 +21,7 @@
 import android.util.Config;
 import android.util.Log;
 
+import java.io.FileDescriptor;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.FileReader;
@@ -378,6 +379,20 @@
     }
 
     /**
+     * Like startMethodTracing(String, int, int), but taking an already-opened
+     * FileDescriptor in which the trace is written.  The file name is also
+     * supplied simply for logging.  Makes a dup of the file descriptor.
+     * 
+     * Not exposed in the SDK unless we are really comfortable with supporting
+     * this and find it would be useful.
+     * @hide
+     */
+    public static void startMethodTracing(String traceName, FileDescriptor fd,
+        int bufferSize, int flags) {
+        VMDebug.startMethodTracing(traceName, fd, bufferSize, flags);
+    }
+
+    /**
      * Determine whether method tracing is currently active.
      * @hide
      */
diff --git a/core/java/android/provider/Browser.java b/core/java/android/provider/Browser.java
index 94254de..2490b8a 100644
--- a/core/java/android/provider/Browser.java
+++ b/core/java/android/provider/Browser.java
@@ -172,6 +172,7 @@
 
     /**
      *  Return a cursor pointing to a list of all the bookmarks.
+     *  Requires {@link android.Manifest.permission#READ_HISTORY_BOOKMARKS}
      *  @param cr   The ContentResolver used to access the database.
      */
     public static final Cursor getAllBookmarks(ContentResolver cr) throws 
@@ -183,6 +184,7 @@
 
     /**
      *  Return a cursor pointing to a list of all visited site urls.
+     *  Requires {@link android.Manifest.permission#READ_HISTORY_BOOKMARKS}
      *  @param cr   The ContentResolver used to access the database.
      */
     public static final Cursor getAllVisitedUrls(ContentResolver cr) throws
@@ -194,6 +196,8 @@
     /**
      *  Update the visited history to acknowledge that a site has been
      *  visited.
+     *  Requires {@link android.Manifest.permission#READ_HISTORY_BOOKMARKS}
+     *  Requires {@link android.Manifest.permission#WRITE_HISTORY_BOOKMARKS}
      *  @param cr   The ContentResolver used to access the database.
      *  @param url  The site being visited.
      *  @param real Whether this is an actual visit, and should be added to the
@@ -243,6 +247,8 @@
      * of them.  This is used to keep our history table to a
      * reasonable size.  Note: it does not prune bookmarks.  If the
      * user wants 1000 bookmarks, the user gets 1000 bookmarks.
+     *  Requires {@link android.Manifest.permission#READ_HISTORY_BOOKMARKS}
+     *  Requires {@link android.Manifest.permission#WRITE_HISTORY_BOOKMARKS}
      *
      * @param cr The ContentResolver used to access the database.
      */
@@ -276,6 +282,7 @@
 
     /**
      * Returns whether there is any history to clear.
+     *  Requires {@link android.Manifest.permission#READ_HISTORY_BOOKMARKS}
      * @param cr   The ContentResolver used to access the database.
      * @return boolean  True if the history can be cleared.
      */
@@ -301,6 +308,7 @@
     /**
      *  Delete all entries from the bookmarks/history table which are
      *  not bookmarks.  Also set all visited bookmarks to unvisited.
+     *  Requires {@link android.Manifest.permission#WRITE_HISTORY_BOOKMARKS}
      *  @param cr   The ContentResolver used to access the database.
      */
     public static final void clearHistory(ContentResolver cr) {
@@ -310,6 +318,8 @@
     /**
      * Helper function to delete all history items and revert all
      * bookmarks to zero visits which meet the criteria provided.
+     *  Requires {@link android.Manifest.permission#READ_HISTORY_BOOKMARKS}
+     *  Requires {@link android.Manifest.permission#WRITE_HISTORY_BOOKMARKS}
      * @param cr   The ContentResolver used to access the database.
      * @param whereClause   String to limit the items affected.
      *                      null means all items.
@@ -372,6 +382,7 @@
 
     /**
      * Delete all history items from begin to end.
+     *  Requires {@link android.Manifest.permission#WRITE_HISTORY_BOOKMARKS}
      * @param cr    The ContentResolver used to access the database.
      * @param begin First date to remove.  If -1, all dates before end.
      *              Inclusive.
@@ -399,6 +410,7 @@
 
     /**
      * Remove a specific url from the history database.
+     *  Requires {@link android.Manifest.permission#WRITE_HISTORY_BOOKMARKS}
      * @param cr    The ContentResolver used to access the database.
      * @param url   url to remove.
      */
@@ -412,6 +424,8 @@
 
     /**
      * Add a search string to the searches database.
+     *  Requires {@link android.Manifest.permission#READ_HISTORY_BOOKMARKS}
+     *  Requires {@link android.Manifest.permission#WRITE_HISTORY_BOOKMARKS}
      * @param cr   The ContentResolver used to access the database.
      * @param search    The string to add to the searches database.
      */
@@ -441,6 +455,7 @@
     }
     /**
      * Remove all searches from the search database.
+     *  Requires {@link android.Manifest.permission#WRITE_HISTORY_BOOKMARKS}
      * @param cr   The ContentResolver used to access the database.
      */
     public static final void clearSearches(ContentResolver cr) {
@@ -455,6 +470,7 @@
     
     /**
      *  Request all icons from the database.
+     *  Requires {@link android.Manifest.permission#READ_HISTORY_BOOKMARKS}
      *  @param  cr The ContentResolver used to access the database.
      *  @param  where Clause to be used to limit the query from the database.
      *          Must be an allowable string to be passed into a database query.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 5aa2174..ebe54fcd 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2545,6 +2545,16 @@
         public static final String GMAIL_DISCARD_ERROR_UPHILL_OP = "gmail_discard_error_uphill_op";
 
         /**
+         * the transcoder URL for mobile devices.
+         */
+        public static final String TRANSCODER_URL = "mobile_transcoder_url";
+
+        /**
+         * URL that points to the privacy terms of the Google Talk service.
+         */
+        public static final String GTALK_TERMS_OF_SERVICE_URL = "gtalk_terms_of_service_url";
+
+        /**
          * Hostname of the GTalk server.
          */
         public static final String GTALK_SERVICE_HOSTNAME = "gtalk_hostname";
diff --git a/core/java/android/provider/Sync.java b/core/java/android/provider/Sync.java
deleted file mode 100644
index c9bde0e..0000000
--- a/core/java/android/provider/Sync.java
+++ /dev/null
@@ -1,649 +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.provider;
-
-import android.content.ContentQueryMap;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.Handler;
-import android.accounts.Account;
-import android.text.TextUtils;
-
-import java.util.Map;
-
-/**
- * The Sync provider stores information used in managing the syncing of the device,
- * including the history and pending syncs.
- * 
- * @hide
- */
-public final class Sync {
-    // utility class
-    private Sync() {}
-
-    /**
-     * The content url for this provider.
-     */
-    public static final Uri CONTENT_URI = Uri.parse("content://sync");
-
-    /**
-     * Columns from the stats table.
-     */
-    public interface StatsColumns {
-        /**
-         * The sync account.
-         * <P>Type: TEXT</P>
-         */
-        public static final String ACCOUNT = "account";
-
-        /**
-         * The sync account type.
-         * <P>Type: TEXT</P>
-         */
-        public static final String ACCOUNT_TYPE = "account_type";
-
-        /**
-         * The content authority (contacts, calendar, etc.).
-         * <P>Type: TEXT</P>
-         */
-        public static final String AUTHORITY = "authority";
-    }
-
-    /**
-     * Provides constants and utility methods to access and use the stats table.
-     */
-    public static final class Stats implements BaseColumns, StatsColumns {
-
-        // utility class
-        private Stats() {}
-
-        /**
-         * The content url for this table.
-         */
-        public static final Uri CONTENT_URI =
-                Uri.parse("content://sync/stats");
-
-        /** Projection for the _id column in the stats table. */
-        public static final String[] SYNC_STATS_PROJECTION = {_ID};
-    }
-
-    /**
-     * Columns from the history table.
-     */
-    public interface HistoryColumns {
-        /**
-         * The ID of the stats row corresponding to this event.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String STATS_ID = "stats_id";
-
-        /**
-         * The source of the sync event (LOCAL, POLL, USER, SERVER).
-         * <P>Type: INTEGER</P>
-         */
-        public static final String SOURCE = "source";
-
-        /**
-         * The type of sync event (START, STOP).
-         * <P>Type: INTEGER</P>
-         */
-        public static final String EVENT = "event";
-
-        /**
-         * The time of the event.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String EVENT_TIME = "eventTime";
-
-        /**
-         * How long this event took. This is only valid if the EVENT is EVENT_STOP.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String ELAPSED_TIME = "elapsedTime";
-
-        /**
-         * Any additional message associated with this event.
-         * <P>Type: TEXT</P>
-         */
-        public static final String MESG = "mesg";
-
-        /**
-         * How much activity was performed sending data to the server. This is sync adapter
-         * specific, but usually is something like how many record update/insert/delete attempts
-         * were carried out. This is only valid if the EVENT is EVENT_STOP.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String UPSTREAM_ACTIVITY = "upstreamActivity";
-
-        /**
-         * How much activity was performed while receiving data from the server.
-         * This is sync adapter specific, but usually is something like how many
-         * records were received from the server. This is only valid if the
-         * EVENT is EVENT_STOP.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String DOWNSTREAM_ACTIVITY = "downstreamActivity";
-    }
-
-    /**
-     * Columns from the history table.
-     */
-    public interface StatusColumns {
-        /**
-         * How many syncs were completed for this account and authority.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String NUM_SYNCS = "numSyncs";
-
-        /**
-         * How long all the events for this account and authority took.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String TOTAL_ELAPSED_TIME = "totalElapsedTime";
-
-        /**
-         * The number of syncs with SOURCE_POLL.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String NUM_SOURCE_POLL = "numSourcePoll";
-
-        /**
-         * The number of syncs with SOURCE_SERVER.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String NUM_SOURCE_SERVER = "numSourceServer";
-
-        /**
-         * The number of syncs with SOURCE_LOCAL.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String NUM_SOURCE_LOCAL = "numSourceLocal";
-
-        /**
-         * The number of syncs with SOURCE_USER.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String NUM_SOURCE_USER = "numSourceUser";
-
-        /**
-         * The time in ms that the last successful sync ended. Will be null if
-         * there are no successful syncs. A successful sync is defined as one having
-         * MESG=MESG_SUCCESS.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String LAST_SUCCESS_TIME = "lastSuccessTime";
-
-        /**
-         * The SOURCE of the last successful sync. Will be null if
-         * there are no successful syncs. A successful sync is defined
-         * as one having MESG=MESG_SUCCESS.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String LAST_SUCCESS_SOURCE = "lastSuccessSource";
-
-        /**
-         * The end time in ms of the last sync that failed since the last successful sync.
-         * Will be null if there are no syncs or if the last one succeeded. A failed
-         * sync is defined as one where MESG isn't MESG_SUCCESS or MESG_CANCELED.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String LAST_FAILURE_TIME = "lastFailureTime";
-
-        /**
-         * The SOURCE of the last sync that failed since the last successful sync.
-         * Will be null if there are no syncs or if the last one succeeded. A failed
-         * sync is defined as one where MESG isn't MESG_SUCCESS or MESG_CANCELED.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String LAST_FAILURE_SOURCE = "lastFailureSource";
-
-        /**
-         * The MESG of the last sync that failed since the last successful sync.
-         * Will be null if there are no syncs or if the last one succeeded. A failed
-         * sync is defined as one where MESG isn't MESG_SUCCESS or MESG_CANCELED.
-         * <P>Type: STRING</P>
-         */
-        public static final String LAST_FAILURE_MESG = "lastFailureMesg";
-
-        /**
-         * Is set to 1 if a sync is pending, 0 if not.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String PENDING = "pending";
-    }
-
-    /**
-     * Provides constants and utility methods to access and use the history
-     * table.
-     */
-    public static class History implements BaseColumns,
-                                                 StatsColumns,
-                                                 HistoryColumns {
-
-        /**
-         * The content url for this table.
-         */
-        public static final Uri CONTENT_URI =
-                Uri.parse("content://sync/history");
-
-        /** Enum value for a sync start event. */
-        public static final int EVENT_START = 0;
-
-        /** Enum value for a sync stop event. */
-        public static final int EVENT_STOP = 1;
-
-        // TODO: i18n -- grab these out of resources.
-        /** String names for the sync event types. */
-        public static final String[] EVENTS = { "START", "STOP" };
-
-        /** Enum value for a server-initiated sync. */
-        public static final int SOURCE_SERVER = 0;
-
-        /** Enum value for a local-initiated sync. */
-        public static final int SOURCE_LOCAL = 1;
-        /**
-         * Enum value for a poll-based sync (e.g., upon connection to
-         * network)
-         */
-        public static final int SOURCE_POLL = 2;
-
-        /** Enum value for a user-initiated sync. */
-        public static final int SOURCE_USER = 3;
-
-        // TODO: i18n -- grab these out of resources.
-        /** String names for the sync source types. */
-        public static final String[] SOURCES = { "SERVER",
-                                                 "LOCAL",
-                                                 "POLL",
-                                                 "USER" };
-
-        // Error types
-        public static final int ERROR_SYNC_ALREADY_IN_PROGRESS = 1;
-        public static final int ERROR_AUTHENTICATION = 2;
-        public static final int ERROR_IO = 3;
-        public static final int ERROR_PARSE = 4;
-        public static final int ERROR_CONFLICT = 5;
-        public static final int ERROR_TOO_MANY_DELETIONS = 6;
-        public static final int ERROR_TOO_MANY_RETRIES = 7;
-        public static final int ERROR_INTERNAL = 8;
-
-        // The MESG column will contain one of these or one of the Error types.
-        public static final String MESG_SUCCESS = "success";
-        public static final String MESG_CANCELED = "canceled";
-
-        private static final String FINISHED_SINCE_WHERE_CLAUSE = EVENT + "=" + EVENT_STOP
-                + " AND " + EVENT_TIME + ">? AND " + ACCOUNT + "=? AND " + ACCOUNT_TYPE + "=?"
-                + " AND " + AUTHORITY + "=?";
-
-        public static String mesgToString(String mesg) {
-            if (MESG_SUCCESS.equals(mesg)) return mesg;
-            if (MESG_CANCELED.equals(mesg)) return mesg;
-            switch (Integer.parseInt(mesg)) {
-                case ERROR_SYNC_ALREADY_IN_PROGRESS: return "already in progress";
-                case ERROR_AUTHENTICATION: return "bad authentication";
-                case ERROR_IO: return "network error";
-                case ERROR_PARSE: return "parse error";
-                case ERROR_CONFLICT: return "conflict detected";
-                case ERROR_TOO_MANY_DELETIONS: return "too many deletions";
-                case ERROR_TOO_MANY_RETRIES: return "too many retries";
-                case ERROR_INTERNAL: return "internal error";
-                default: return "unknown error";
-            }
-        }
-
-        // utility class
-        private History() {}
-
-        /**
-         * returns a cursor that queries the sync history in descending event time order
-         * @param contentResolver the ContentResolver to use for the query
-         * @return the cursor on the History table
-         */
-        public static Cursor query(ContentResolver contentResolver) {
-            return contentResolver.query(CONTENT_URI, null, null, null, EVENT_TIME + " desc");
-        }
-
-        public static boolean hasNewerSyncFinished(ContentResolver contentResolver,
-                Account account, String authority, long when) {
-            Cursor c = contentResolver.query(CONTENT_URI, new String[]{_ID},
-                    FINISHED_SINCE_WHERE_CLAUSE,
-                    new String[]{Long.toString(when), account.mName, account.mType, authority},
-                    null);
-            try {
-              return c.getCount() > 0;
-            } finally {
-                c.close();
-            }
-        }
-    }
-
-    /**
-     * Provides constants and utility methods to access and use the authority history
-     * table, which contains information about syncs aggregated by account and authority.
-     * All the HistoryColumns except for EVENT are present, plus the AuthorityHistoryColumns.
-     */
-    public static class Status extends History implements StatusColumns {
-
-        /**
-         * The content url for this table.
-         */
-        public static final Uri CONTENT_URI = Uri.parse("content://sync/status");
-
-        // utility class
-        private Status() {}
-
-        /**
-         * returns a cursor that queries the authority sync history in descending event order of
-         * ACCOUNT, AUTHORITY
-         * @param contentResolver the ContentResolver to use for the query
-         * @return the cursor on the AuthorityHistory table
-         */
-        public static Cursor query(ContentResolver contentResolver) {
-            return contentResolver.query(CONTENT_URI, null, null, null,
-                    ACCOUNT_TYPE + "," + ACCOUNT + "," + AUTHORITY);
-        }
-
-        public static class QueryMap extends ContentQueryMap {
-            public QueryMap(ContentResolver contentResolver,
-                    boolean keepUpdated,
-                    Handler handlerForUpdateNotifications) {
-                super(contentResolver.query(CONTENT_URI, null, null, null, null),
-                        _ID, keepUpdated, handlerForUpdateNotifications);
-            }
-
-            public ContentValues get(Account account, String authority) {
-                Map<String, ContentValues> rows = getRows();
-                for (ContentValues values : rows.values()) {
-                    if (values.getAsString(ACCOUNT).equals(account.mName)
-                            && values.getAsString(ACCOUNT_TYPE).equals(account.mType)
-                            && values.getAsString(AUTHORITY).equals(authority)) {
-                        return values;
-                    }
-                }
-                return null;
-            }
-        }
-    }
-
-    /**
-     * Provides constants and utility methods to access and use the pending syncs table
-     */
-    public static final class Pending implements BaseColumns,
-                                                 StatsColumns {
-
-        /**
-         * The content url for this table.
-         */
-        public static final Uri CONTENT_URI = Uri.parse("content://sync/pending");
-
-        // utility class
-        private Pending() {}
-
-        public static class QueryMap extends ContentQueryMap {
-            public QueryMap(ContentResolver contentResolver, boolean keepUpdated,
-                    Handler handlerForUpdateNotifications) {
-                super(contentResolver.query(CONTENT_URI, null, null, null, null), _ID, keepUpdated,
-                        handlerForUpdateNotifications);
-            }
-
-            public boolean isPending(Account account, String authority) {
-                Map<String, ContentValues> rows = getRows();
-                for (ContentValues values : rows.values()) {
-                    if (values.getAsString(ACCOUNT).equals(account.mName)
-                            && values.getAsString(ACCOUNT_TYPE).equals(account.mType)
-                            && values.getAsString(AUTHORITY).equals(authority)) {
-                        return true;
-                    }
-                }
-                return false;
-            }
-        }
-    }
-
-    /**
-     * Columns from the history table.
-     */
-    public interface ActiveColumns {
-        /**
-         * The wallclock time of when the active sync started.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String START_TIME = "startTime";
-    }
-
-    /**
-     * Provides constants and utility methods to access and use the pending syncs table
-     */
-    public static final class Active implements BaseColumns,
-                                                StatsColumns,
-                                                ActiveColumns {
-
-        /**
-         * The content url for this table.
-         */
-        public static final Uri CONTENT_URI = Uri.parse("content://sync/active");
-
-        // utility class
-        private Active() {}
-
-        public static class QueryMap extends ContentQueryMap {
-            public QueryMap(ContentResolver contentResolver, boolean keepUpdated,
-                    Handler handlerForUpdateNotifications) {
-                super(contentResolver.query(CONTENT_URI, null, null, null, null), _ID, keepUpdated,
-                        handlerForUpdateNotifications);
-            }
-
-            public ContentValues getActiveSyncInfo() {
-                Map<String, ContentValues> rows = getRows();
-                for (ContentValues values : rows.values()) {
-                    return values;
-                }
-                return null;
-            }
-
-            public Account getSyncingAccount() {
-                ContentValues values = getActiveSyncInfo();
-                if (values == null || TextUtils.isEmpty(values.getAsString(ACCOUNT))) {
-                    return null;
-                }
-                return new Account(values.getAsString(ACCOUNT), values.getAsString(ACCOUNT_TYPE));
-            }
-
-            public String getSyncingAuthority() {
-                ContentValues values = getActiveSyncInfo();
-                return (values == null) ? null : values.getAsString(AUTHORITY);
-            }
-
-            public long getSyncStartTime() {
-                ContentValues values = getActiveSyncInfo();
-                return (values == null) ? -1 : values.getAsLong(START_TIME);
-            }
-        }
-    }
-
-    /**
-     * Columns in the settings table, which holds key/value pairs of settings.
-     */
-    public interface SettingsColumns {
-        /**
-         * The key of the setting
-         * <P>Type: TEXT</P>
-         */
-        public static final String KEY = "name";
-
-        /**
-         * The value of the settings
-         * <P>Type: TEXT</P>
-         */
-        public static final String VALUE = "value";
-    }
-
-    /**
-     * Provides constants and utility methods to access and use the settings
-     * table.
-     */
-    public static final class Settings implements BaseColumns, SettingsColumns {
-        /**
-         * The Uri of the settings table. This table behaves a little differently than
-         * normal tables. Updates are not allowed, only inserts, and inserts cause a replace
-         * to be performed, which first deletes the row if it is already present.
-         */
-        public static final Uri CONTENT_URI = Uri.parse("content://sync/settings");
-
-        /** controls whether or not the device listens for sync tickles */
-        public static final String SETTING_LISTEN_FOR_TICKLES = "listen_for_tickles";
-
-        /** controls whether or not the individual provider is synced when tickles are received */
-        public static final String SETTING_SYNC_PROVIDER_PREFIX = "sync_provider_";
-
-        /** query column project */
-        private static final String[] PROJECTION = { KEY, VALUE };
-
-        /**
-         * Convenience function for updating a single settings value as a
-         * boolean. This will either create a new entry in the table if the
-         * given name does not exist, or modify the value of the existing row
-         * with that name.  Note that internally setting values are always
-         * stored as strings, so this function converts the given value to a
-         * string before storing it.
-         *
-         * @param contentResolver the ContentResolver to use to access the settings table
-         * @param name The name of the setting to modify.
-         * @param val The new value for the setting.
-         */
-        static private void putBoolean(ContentResolver contentResolver, String name, boolean val) {
-            ContentValues values = new ContentValues();
-            values.put(KEY, name);
-            values.put(VALUE, Boolean.toString(val));
-            // this insert is translated into an update by the underlying Sync provider
-            contentResolver.insert(CONTENT_URI, values);
-        }
-
-        /**
-         * Convenience function for getting a setting value as a boolean without using the
-         * QueryMap for light-weight setting querying.
-         * @param contentResolver The ContentResolver for querying the setting.
-         * @param name The name of the setting to query
-         * @param def The default value for the setting.
-         * @return The value of the setting.
-         */
-        static public boolean getBoolean(ContentResolver contentResolver,
-                String name, boolean def) {
-            Cursor cursor = contentResolver.query(
-                    CONTENT_URI,
-                    PROJECTION,
-                    KEY + "=?",
-                    new String[] { name },
-                    null);
-            try {
-                if (cursor != null && cursor.moveToFirst()) {
-                    return Boolean.parseBoolean(cursor.getString(1));
-                }
-            } finally {
-                if (cursor != null) cursor.close();
-            }
-            return def;
-        }
-
-        /**
-         * A convenience method to set whether or not the provider is synced when
-         * it receives a network tickle.
-         *
-         * @param contentResolver the ContentResolver to use to access the settings table
-         * @param providerName the provider whose behavior is being controlled
-         * @param sync true if the provider should be synced when tickles are received for it
-         */
-        static public void setSyncProviderAutomatically(ContentResolver contentResolver,
-                String providerName, boolean sync) {
-            putBoolean(contentResolver, SETTING_SYNC_PROVIDER_PREFIX + providerName, sync);
-        }
-
-        /**
-         * A convenience method to set whether or not the device should listen to tickles.
-         *
-         * @param contentResolver the ContentResolver to use to access the settings table
-         * @param flag true if it should listen.
-         */
-        static public void setListenForNetworkTickles(ContentResolver contentResolver,
-                boolean flag) {
-            putBoolean(contentResolver, SETTING_LISTEN_FOR_TICKLES, flag);
-        }
-
-        public static class QueryMap extends ContentQueryMap {
-            private ContentResolver mContentResolver;
-
-            public QueryMap(ContentResolver contentResolver, boolean keepUpdated,
-                    Handler handlerForUpdateNotifications) {
-                super(contentResolver.query(CONTENT_URI, null, null, null, null), KEY, keepUpdated,
-                        handlerForUpdateNotifications);
-                mContentResolver = contentResolver;
-            }
-
-            /**
-             * Check if the provider should be synced when a network tickle is received
-             * @param providerName the provider whose setting we are querying
-             * @return true of the provider should be synced when a network tickle is received
-             */
-            public boolean getSyncProviderAutomatically(String providerName) {
-                return getBoolean(SETTING_SYNC_PROVIDER_PREFIX + providerName, true);
-            }
-
-            /**
-             * Set whether or not the provider is synced when it receives a network tickle.
-             *
-             * @param providerName the provider whose behavior is being controlled
-             * @param sync true if the provider should be synced when tickles are received for it
-             */
-            public void setSyncProviderAutomatically(String providerName, boolean sync) {
-                Settings.setSyncProviderAutomatically(mContentResolver, providerName, sync);
-            }
-
-            /**
-             * Set whether or not the device should listen for tickles.
-             *
-             * @param flag true if it should listen.
-             */
-            public void setListenForNetworkTickles(boolean flag) {
-                Settings.setListenForNetworkTickles(mContentResolver, flag);
-            }
-
-            /**
-             * Check if the device should listen to tickles.
-
-             * @return true if it should
-             */
-            public boolean getListenForNetworkTickles() {
-                return getBoolean(SETTING_LISTEN_FOR_TICKLES, true);
-            }
-
-            /**
-             * Convenience function for retrieving a single settings value
-             * as a boolean.
-             *
-             * @param name The name of the setting to retrieve.
-             * @param def Value to return if the setting is not defined.
-             * @return The setting's current value, or 'def' if it is not defined.
-             */
-            private boolean getBoolean(String name, boolean def) {
-                ContentValues values = getValues(name);
-                return values != null ? values.getAsBoolean(VALUE) : def;
-            }
-        }
-    }
-}
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 0d96ec3..a301d7b 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -247,7 +247,7 @@
             if (uri == null) {
                 return false;
             }
-            
+
             boolean markAsUnread = false;
             boolean markAsRead = false;
             switch(folder) {
@@ -274,7 +274,7 @@
             } else if (markAsRead) {
                 values.put(READ, Integer.valueOf(1));
             }
-            
+
             return 1 == SqliteWrapper.update(context, context.getContentResolver(),
                             uri, values, null, null);
         }
@@ -1422,6 +1422,8 @@
              */
             public static final String _DATA = "_data";
 
+            public static final String TEXT = "text";
+
         }
 
         public static final class Rate {
@@ -1498,10 +1500,10 @@
 
         public static final Uri CONTENT_DRAFT_URI = Uri.parse(
                 "content://mms-sms/draft");
-        
+
         /***
          * Pass in a query parameter called "pattern" which is the text
-         * to search for.    
+         * to search for.
          * The sort order is fixed to be thread_id ASC,date DESC.
          */
         public static final Uri SEARCH_URI = Uri.parse(
diff --git a/core/java/android/server/search/Searchables.java b/core/java/android/server/search/Searchables.java
index a27667b..c7cc8ed 100644
--- a/core/java/android/server/search/Searchables.java
+++ b/core/java/android/server/search/Searchables.java
@@ -57,6 +57,11 @@
     private SearchableInfo mDefaultSearchable = null;
     private SearchableInfo mDefaultSearchableForWebSearch = null;
 
+    public static String GOOGLE_SEARCH_COMPONENT_NAME =
+            "com.android.googlesearch/.GoogleSearch";
+    public static String ENHANCED_GOOGLE_SEARCH_COMPONENT_NAME =
+            "com.google.android.providers.enhancedgooglesearch/.Launcher";
+
     /**
      *
      * @param context Context to use for looking up activities etc.
@@ -341,6 +346,18 @@
                     return component;
                 }
             }
+        } else {
+            // If the current preferred activity is GoogleSearch, and we detect
+            // EnhancedGoogleSearch installed as well, set the latter as preferred since that
+            // is a superset and provides more functionality.
+            ComponentName cn = new ComponentName(ri.activityInfo.packageName, ri.activityInfo.name);
+            if (cn.flattenToShortString().equals(GOOGLE_SEARCH_COMPONENT_NAME)) {
+                ComponentName enhancedGoogleSearch = ComponentName.unflattenFromString(
+                        ENHANCED_GOOGLE_SEARCH_COMPONENT_NAME);
+                if (setPreferredActivity(enhancedGoogleSearch, Intent.ACTION_WEB_SEARCH)) {
+                    return enhancedGoogleSearch;
+                }
+            }
         }
 
         if (ri == null) return null;
diff --git a/core/java/android/speech/tts/ITts.aidl b/core/java/android/speech/tts/ITts.aidl
index 02211fd..75c3b30 100755
--- a/core/java/android/speech/tts/ITts.aidl
+++ b/core/java/android/speech/tts/ITts.aidl
@@ -29,6 +29,8 @@
 interface ITts {

     void setSpeechRate(in int speechRate);

 

+    void setPitch(in int pitch);

+

     void speak(in String text, in int queueMode, in String[] params);

 

     boolean isSpeaking();

diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 9fc143d..c064284 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -450,7 +450,6 @@
     }
 
 
-
     /**
      * Sets the speech rate for the TTS engine.
      *
@@ -483,6 +482,37 @@
 
 
     /**
+     * Sets the speech pitch for the TTS engine.
+     *
+     * Note that the pitch is not universally supported by all engines and
+     * will be treated as a hint. The TTS library will try to use the specified
+     * pitch, but there is no guarantee.
+     * This has no effect on any pre-recorded speech.
+     *
+     * @param pitch
+     *            The pitch for the TTS engine. 1 is the normal pitch,
+     *            lower values lower the tone of the synthesized voice,
+     *            greater values increase it.
+     */
+    public void setPitch(float pitch) {
+        synchronized (mStartLock) {
+            if (!mStarted) {
+                return;
+            }
+            try {
+                if (pitch > 0) {
+                    mITts.setPitch((int)(pitch*100));
+                }
+            } catch (RemoteException e) {
+                // TTS died; restart it.
+                mStarted = false;
+                initTts();
+            }
+        }
+    }
+
+
+    /**
      * Sets the language for the TTS engine.
      *
      * Note that the language is not universally supported by all engines and
diff --git a/core/java/android/syncml/pim/vcard/ContactStruct.java b/core/java/android/syncml/pim/vcard/ContactStruct.java
index 5a29112..4b4c394 100644
--- a/core/java/android/syncml/pim/vcard/ContactStruct.java
+++ b/core/java/android/syncml/pim/vcard/ContactStruct.java
@@ -38,6 +38,7 @@
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -181,6 +182,34 @@
         organizationList.add(organizationData);
     }
 
+    /**
+     * Set "position" value to the appropriate data. If there's more than one
+     * OrganizationData objects, the value is set to the last one. If there's no
+     * OrganizationData object, a new OrganizationData is created, whose company name is
+     * empty.  
+     * 
+     * TODO: incomplete logic. fix this:
+     * 
+     * e.g. This assumes ORG comes earlier, but TITLE may come earlier like this, though we do not
+     * know how to handle it in general cases...
+     * ----
+     * TITLE:Software Engineer
+     * ORG:Google
+     * ----
+     */
+    public void setPosition(String positionValue) {
+        if (organizationList == null) {
+            organizationList = new ArrayList<OrganizationData>();
+        }
+        int size = organizationList.size();
+        if (size == 0) {
+            addOrganization(Contacts.OrganizationColumns.TYPE_OTHER, "", null, false);
+            size = 1;
+        }
+        OrganizationData lastData = organizationList.get(size - 1);
+        lastData.positionName = positionValue;
+    }
+    
     public void addExtension(PropertyNode propertyNode) {
         if (propertyNode.propValue.length() == 0) {
             return;
@@ -427,8 +456,6 @@
             } else if (name.equals("ORG")) {
                 // vCard specification does not specify other types.
                 int type = Contacts.OrganizationColumns.TYPE_WORK;
-                String companyName = "";
-                String positionName = "";
                 boolean isPrimary = false;
                 
                 for (String typeString : propertyNode.paramMap_TYPE) {
@@ -442,29 +469,20 @@
                 }
 
                 List<String> list = propertyNode.propValue_vector; 
-                int size = list.size(); 
-                if (size > 1) {
-                    companyName = list.get(0);
-                    StringBuilder builder = new StringBuilder();
-                    for (int i = 1; i < size; i++) {
-                        builder.append(list.get(1));
-                        if (i != size - 1) {
-                            builder.append(", ");
-                        }
+                int size = list.size();
+                StringBuilder builder = new StringBuilder();
+                for (Iterator<String> iter = list.iterator(); iter.hasNext();) {
+                    builder.append(iter.next());
+                    if (iter.hasNext()) {
+                        builder.append(' ');
                     }
-                    positionName = builder.toString();
-                } else if (size == 1) {
-                    companyName = propertyNode.propValue;
-                    positionName = "";
                 }
-                contact.addOrganization(type, companyName, positionName, isPrimary);
+
+                contact.addOrganization(type, builder.toString(), "", isPrimary);
             } else if (name.equals("TITLE")) {
-                contact.title = propertyNode.propValue;
-                // XXX: What to do this? Isn't ORG enough?
-                contact.addExtension(propertyNode);
+                contact.setPosition(propertyNode.propValue);
             } else if (name.equals("ROLE")) {
-                // XXX: What to do this? Isn't ORG enough?
-                contact.addExtension(propertyNode);
+                contact.setPosition(propertyNode.propValue);
             } else if (name.equals("PHOTO")) {
                 // We prefer PHOTO to LOGO.
                 String valueType = propertyNode.paramMap.getAsString("VALUE");
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index a095913..d89ada0 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -106,16 +106,8 @@
      * {@hide}
      */
     public void updateMetrics(CompatibilityInfo compatibilityInfo, int orientation) {
-        if (compatibilityInfo.mScalingRequired) {
-            float invertedRatio = compatibilityInfo.mApplicationInvertedScale;
-            density *= invertedRatio;
-            scaledDensity *= invertedRatio;
-            xdpi *= invertedRatio;
-            ydpi *= invertedRatio;
-            widthPixels *= invertedRatio;
-            heightPixels *= invertedRatio;
-        }
-        if (!compatibilityInfo.mConfiguredExpandable) {
+        int xOffset = 0;
+        if (!compatibilityInfo.isConfiguredExpandable()) {
             // Note: this assume that configuration is updated before calling
             // updateMetrics method.
             int defaultWidth;
@@ -141,11 +133,13 @@
             
             if (defaultWidth == widthPixels && defaultHeight == heightPixels) {
                 // the screen size is same as expected size. make it expandable
-                compatibilityInfo.mExpandable = true;
+                compatibilityInfo.setExpandable(true);
             } else {
-                compatibilityInfo.mExpandable = false;
+                compatibilityInfo.setExpandable(false);
                 // adjust the size only when the device's screen is bigger.
                 if (defaultWidth < widthPixels) {
+                    // content/window's x offset in original pixels
+                    xOffset = ((widthPixels - defaultWidth) / 2);
                     widthPixels = defaultWidth;
                 }
                 if (defaultHeight < heightPixels) {
@@ -153,8 +147,19 @@
                 }
             }
         }
+        compatibilityInfo.setVisibleRect(xOffset, widthPixels, heightPixels);
+        if (compatibilityInfo.isScalingRequired()) {
+            float invertedRatio = compatibilityInfo.applicationInvertedScale;
+            density *= invertedRatio;
+            scaledDensity *= invertedRatio;
+            xdpi *= invertedRatio;
+            ydpi *= invertedRatio;
+            widthPixels *= invertedRatio;
+            heightPixels *= invertedRatio;
+        }
     }
 
+    @Override
     public String toString() {
         return "DisplayMetrics{density=" + density + ", width=" + widthPixels +
             ", height=" + heightPixels + ", scaledDensity=" + scaledDensity +
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 69c6a7c..0e37b26 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -270,28 +270,47 @@
     }
 
     /**
-     * Scales down the cood of this event by the given scale.
+     * Scales down the coordination of this event by the given scale.
      *
      * @hide
      */
     public void scale(float scale) {
-        if (scale != 1.0f) {
-            mX *= scale;
-            mY *= scale;
-            mRawX *= scale;
-            mRawY *= scale;
-            mSize *= scale;
-            mXPrecision *= scale;
-            mYPrecision *= scale;
-            if (mHistory != null) {
-                float[] history = mHistory;
-                int length = history.length;
-                for (int i = 0; i < length; i += 4) {
-                    history[i] *= scale;        // X
-                                                // history[i + 2] == pressure
-                    history[i + 1] *= scale;    // Y
-                    history[i + 3] *= scale;    // Size, TODO: square this?
-                }
+        mX *= scale;
+        mY *= scale;
+        mRawX *= scale;
+        mRawY *= scale;
+        mSize *= scale;
+        mXPrecision *= scale;
+        mYPrecision *= scale;
+        if (mHistory != null) {
+            float[] history = mHistory;
+            int length = history.length;
+            for (int i = 0; i < length; i += 4) {
+                history[i] *= scale;        // X
+                history[i + 1] *= scale;    // Y
+                // no need to scale pressure ([i+2])
+                history[i + 3] *= scale;    // Size, TODO: square this?
+            }
+        }
+    }
+
+    /**
+     * Translate the coordination of the event by given x and y.
+     *
+     * @hide
+     */
+    public void translate(float dx, float dy) {
+        mX += dx;
+        mY += dy;
+        mRawX += dx;
+        mRawY += dx;
+        if (mHistory != null) {
+            float[] history = mHistory;
+            int length = history.length;
+            for (int i = 0; i < length; i += 4) {
+                history[i] += dx;        // X
+                history[i + 1] += dy;    // Y
+                // no need to translate pressure (i+2) and size (i+3) 
             }
         }
     }
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 6519852..1e2bc1f 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.content.res.CompatibilityInfo;
+import android.content.res.CompatibilityInfo.Translator;
 import android.graphics.Canvas;
 import android.graphics.PixelFormat;
 import android.graphics.PorterDuff;
@@ -139,24 +140,21 @@
     int mFormat = -1;
     int mType = -1;
     final Rect mSurfaceFrame = new Rect();
-    private final CompatibilityInfo mCompatibilityInfo;
+    private Translator mTranslator;
 
     public SurfaceView(Context context) {
         super(context);
         setWillNotDraw(true);
-        mCompatibilityInfo = context.getResources().getCompatibilityInfo();
     }
     
     public SurfaceView(Context context, AttributeSet attrs) {
         super(context, attrs);
         setWillNotDraw(true);
-        mCompatibilityInfo = context.getResources().getCompatibilityInfo();
     }
 
     public SurfaceView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
         setWillNotDraw(true);
-        mCompatibilityInfo = context.getResources().getCompatibilityInfo();
     }
     
     /**
@@ -259,9 +257,9 @@
     public boolean dispatchTouchEvent(MotionEvent event) {
         // SurfaceView uses pre-scaled size unless fixed size is requested. This hook
         // scales the event back to the pre-scaled coordinates for such surface.
-        if (mRequestedWidth < 0 && mCompatibilityInfo.mScalingRequired) {
+        if (mRequestedWidth < 0 && mTranslator != null) {
             MotionEvent scaledBack = MotionEvent.obtain(event);
-            scaledBack.scale(mCompatibilityInfo.mApplicationScale);
+            scaledBack.scale(mTranslator.applicationScale);
             try {
                 return super.dispatchTouchEvent(scaledBack);
             } finally {
@@ -298,15 +296,18 @@
         if (!mHaveFrame) {
             return;
         }
-        float appScale = mCompatibilityInfo.mApplicationScale;
+        mTranslator = ((ViewRoot)getRootView().getParent()).mTranslator;
+
+        float appScale = mTranslator == null ? 1.0f : mTranslator.applicationScale;
         
         int myWidth = mRequestedWidth;
         if (myWidth <= 0) myWidth = getWidth();
         int myHeight = mRequestedHeight;
         if (myHeight <= 0) myHeight = getHeight();
 
-        // Use original size for surface unless fixed size is requested.
-        if (mRequestedWidth <= 0 && mCompatibilityInfo.mScalingRequired) {
+        // Use original size if the app specified the size of the view,
+        // and let the flinger to scale up.
+        if (mRequestedWidth <= 0 && mTranslator != null && mTranslator.scalingRequired) {
             myWidth *= appScale;
             myHeight *= appScale;
         }
@@ -326,7 +327,7 @@
                     + " visible=" + visibleChanged
                     + " left=" + (mLeft != mLocation[0])
                     + " top=" + (mTop != mLocation[1]));
-            
+
             try {
                 final boolean visible = mVisible = mRequestedVisible;
                 mLeft = mLocation[0];
@@ -336,16 +337,23 @@
                 mFormat = mRequestedFormat;
                 mType = mRequestedType;
 
-                // Scaling window's layout here because mLayout is not used elsewhere.
-                mLayout.x = (int) (mLeft * appScale);
-                mLayout.y = (int) (mTop * appScale);
-                mLayout.width = (int) (getWidth() * appScale);
-                mLayout.height = (int) (getHeight() * appScale);
+                // Scaling/Translate window's layout here because mLayout is not used elsewhere.
+                
+                // Places the window relative
+                mLayout.x = mLeft;
+                mLayout.y = mTop;
+                mLayout.width = getWidth();
+                mLayout.height = getHeight();
+                if (mTranslator != null) {
+                    mTranslator.translateLayoutParamsInAppWindowToScreen(mLayout);
+                }
+                
                 mLayout.format = mRequestedFormat;
                 mLayout.flags |=WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
                               | WindowManager.LayoutParams.FLAG_SCALED
                               | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                               | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
+                              | WindowManager.LayoutParams.FLAG_NO_COMPATIBILITY_SCALING
                               ;
 
                 mLayout.memoryType = mRequestedType;
@@ -372,13 +380,6 @@
                         visible ? VISIBLE : GONE, false, mWinFrame, mContentInsets,
                         mVisibleInsets, mSurface);
 
-                if (mCompatibilityInfo.mScalingRequired) {
-                    float invertedScale = mCompatibilityInfo.mApplicationInvertedScale;
-                    mContentInsets.scale(invertedScale);
-                    mVisibleInsets.scale(invertedScale);
-                    mWinFrame.scale(invertedScale);
-                }
-
                 if (localLOGV) Log.i(TAG, "New surface: " + mSurface
                         + ", vis=" + visible + ", frame=" + mWinFrame);
                 mSurfaceFrame.left = 0;
@@ -447,24 +448,14 @@
 
     private static class MyWindow extends IWindow.Stub {
         private final WeakReference<SurfaceView> mSurfaceView;
-        private final CompatibilityInfo mCompatibilityInfo;
 
         public MyWindow(SurfaceView surfaceView) {
             mSurfaceView = new WeakReference<SurfaceView>(surfaceView);
-            mCompatibilityInfo = surfaceView.getContext().getResources().getCompatibilityInfo();
         }
 
         public void resized(int w, int h, Rect coveredInsets,
                 Rect visibleInsets, boolean reportDraw) {
             SurfaceView surfaceView = mSurfaceView.get();
-            if (mCompatibilityInfo.mScalingRequired) {
-                float scale = mCompatibilityInfo.mApplicationInvertedScale;
-                w *= scale;
-                h *= scale;
-                coveredInsets.scale(scale);
-                visibleInsets.scale(scale);
-            }
-
             if (surfaceView != null) {
                 if (localLOGV) Log.v(
                         "SurfaceView", surfaceView + " got resized: w=" +
@@ -627,9 +618,6 @@
             Canvas c = null;
             if (!mDrawingStopped && mWindow != null) {
                 Rect frame = dirty != null ? dirty : mSurfaceFrame;
-                if (mCompatibilityInfo.mScalingRequired) {
-                    frame.scale(mCompatibilityInfo.mApplicationScale);
-                }
                 try {
                     c = mSurface.lockCanvas(frame);
                 } catch (Exception e) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ec8fd96..3bfdde8 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1934,11 +1934,13 @@
                         viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
                         viewFlagMasks |= SOUND_EFFECTS_ENABLED;
                     }
+                    break;
                 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
                     if (!a.getBoolean(attr, true)) {
                         viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
                         viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
                     }
+                    break;
                 case R.styleable.View_scrollbars:
                     final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
                     if (scrollbars != SCROLLBARS_NONE) {
@@ -6541,7 +6543,7 @@
         boolean changed = false;
 
         if (DBG) {
-            System.out.println(this + " View.setFrame(" + left + "," + top + ","
+            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
                     + right + "," + bottom + ")");
         }
 
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index fe5edc2..a12b14a 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -131,13 +131,12 @@
     Rect mDirty; // will be a graphics.Region soon
     boolean mIsAnimating;
 
-    private CompatibilityInfo mCompatibilityInfo;
+    CompatibilityInfo.Translator mTranslator;
 
     final View.AttachInfo mAttachInfo;
 
     final Rect mTempRect; // used in the transaction to not thrash the heap.
     final Rect mVisRect; // used to retrieve visible rect of focused view.
-    final Point mVisPoint; // used to retrieve global offset of focused view.
 
     boolean mTraversalScheduled;
     boolean mWillDrawSoon;
@@ -225,7 +224,6 @@
         mDirty = new Rect();
         mTempRect = new Rect();
         mVisRect = new Rect();
-        mVisPoint = new Point();
         mWinFrame = new Rect();
         mWindow = new W(this, context);
         mInputMethodCallback = new InputMethodCallback(this);
@@ -394,20 +392,25 @@
             if (mView == null) {
                 mView = view;
                 mWindowAttributes.copyFrom(attrs);
-                mCompatibilityInfo = mView.getContext().getResources().getCompatibilityInfo();
+
+                CompatibilityInfo compatibilityInfo =
+                        mView.getContext().getResources().getCompatibilityInfo();
+                mTranslator = compatibilityInfo.getTranslator(attrs);
                 boolean restore = false;
-                if (mCompatibilityInfo.mScalingRequired || !mCompatibilityInfo.mExpandable) {
+                if (attrs != null && mTranslator != null) {
                     restore = true;
-                    mWindowAttributes.backup();
+                    attrs.backup();
+                    mTranslator.translateWindowLayout(attrs);
                 }
-                if (!mCompatibilityInfo.mExpandable) {
-                    adjustWindowAttributesForCompatibleMode(mWindowAttributes);
-                }
+                if (DEBUG_LAYOUT) Log.d(TAG, "WindowLayout in setView:" + attrs);
+
                 mSoftInputMode = attrs.softInputMode;
                 mWindowAttributesChanged = true;
                 mAttachInfo.mRootView = view;
-                mAttachInfo.mScalingRequired = mCompatibilityInfo.mScalingRequired;
-                mAttachInfo.mApplicationScale = mCompatibilityInfo.mApplicationScale;
+                mAttachInfo.mScalingRequired =
+                        mTranslator == null ? false : mTranslator.scalingRequired;
+                mAttachInfo.mApplicationScale =
+                        mTranslator == null ? 1.0f : mTranslator.applicationScale;
                 if (panelParentView != null) {
                     mAttachInfo.mPanelParentWindowToken
                             = panelParentView.getApplicationWindowToken();
@@ -428,15 +431,14 @@
                     mAttachInfo.mRootView = null;
                     unscheduleTraversals();
                     throw new RuntimeException("Adding window failed", e);
+                } finally {
+                    if (restore) {
+                        attrs.restore();
+                    }
                 }
 
-                if (restore) {
-                    mWindowAttributes.restore();
-                }
-
-                if (mCompatibilityInfo.mScalingRequired) {
-                    mAttachInfo.mContentInsets.scale(
-                            mCompatibilityInfo.mApplicationInvertedScale);
+                if (mTranslator != null) {
+                    mTranslator.translateRectInScreenToAppWindow(mAttachInfo.mContentInsets);
                 }
                 mPendingContentInsets.set(mAttachInfo.mContentInsets);
                 mPendingVisibleInsets.set(0, 0, 0, 0);
@@ -548,14 +550,14 @@
 
     public void invalidateChild(View child, Rect dirty) {
         checkThread();
-        if (LOCAL_LOGV) Log.v(TAG, "Invalidate child: " + dirty);
-        if (mCurScrollY != 0 || mCompatibilityInfo.mScalingRequired) {
+        if (DEBUG_DRAW) Log.v(TAG, "Invalidate child: " + dirty);
+        if (mCurScrollY != 0 || mTranslator != null) {
             mTempRect.set(dirty);
             if (mCurScrollY != 0) {
                mTempRect.offset(0, -mCurScrollY);
             }
-            if (mCompatibilityInfo.mScalingRequired) {
-                mTempRect.scale(mCompatibilityInfo.mApplicationScale);
+            if (mTranslator != null) {
+                mTranslator.translateRectInAppWindowToScreen(mTempRect);
             }
             dirty = mTempRect;
         }
@@ -574,7 +576,7 @@
         return null;
     }
 
-     public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset) {
+    public boolean getChildVisibleRect(View child, Rect r, android.graphics.Point offset) {
         if (child != mView) {
             throw new RuntimeException("child is not mine, honest!");
         }
@@ -635,14 +637,14 @@
         boolean viewVisibilityChanged = mViewVisibility != viewVisibility
                 || mNewSurfaceNeeded;
 
-        float appScale = mCompatibilityInfo.mApplicationScale;
+        float appScale = mAttachInfo.mApplicationScale;
 
         WindowManager.LayoutParams params = null;
         if (mWindowAttributesChanged) {
             mWindowAttributesChanged = false;
             params = lp;
         }
-
+        Rect frame = mWinFrame;
         if (mFirst) {
             fullRedrawNeeded = true;
             mLayoutRequested = true;
@@ -667,11 +669,11 @@
             //Log.i(TAG, "Screen on initialized: " + attachInfo.mKeepScreenOn);
 
         } else {
-            desiredWindowWidth = mWinFrame.width();
-            desiredWindowHeight = mWinFrame.height();
+            desiredWindowWidth = frame.width();
+            desiredWindowHeight = frame.height();
             if (desiredWindowWidth != mWidth || desiredWindowHeight != mHeight) {
                 if (DEBUG_ORIENTATION) Log.v("ViewRoot",
-                        "View " + host + " resized to: " + mWinFrame);
+                        "View " + host + " resized to: " + frame);
                 fullRedrawNeeded = true;
                 mLayoutRequested = true;
                 windowResizesToFitContent = true;
@@ -817,7 +819,6 @@
                 }
             }
 
-            final Rect frame = mWinFrame;
             boolean initialized = false;
             boolean contentInsetsChanged = false;
             boolean visibleInsetsChanged;
@@ -890,7 +891,7 @@
             } catch (RemoteException e) {
             }
             if (DEBUG_ORIENTATION) Log.v(
-                    "ViewRoot", "Relayout returned: frame=" + mWinFrame + ", surface=" + mSurface);
+                    "ViewRoot", "Relayout returned: frame=" + frame + ", surface=" + mSurface);
 
             attachInfo.mWindowLeft = frame.left;
             attachInfo.mWindowTop = frame.top;
@@ -965,7 +966,6 @@
             if (Config.DEBUG && ViewDebug.profileLayout) {
                 startTime = SystemClock.elapsedRealtime();
             }
-
             host.layout(0, 0, host.mMeasuredWidth, host.mMeasuredHeight);
 
             if (Config.DEBUG && ViewDebug.consistencyCheckEnabled) {
@@ -992,7 +992,10 @@
                         mTmpLocation[1] + host.mBottom - host.mTop);
 
                 host.gatherTransparentRegion(mTransparentRegion);
-                mTransparentRegion.scale(appScale);
+                if (mTranslator != null) {
+                    mTranslator.translateRegionInWindowToScreen(mTransparentRegion);
+                }
+
                 if (!mTransparentRegion.equals(mPreviousTransparentRegion)) {
                     mPreviousTransparentRegion.set(mTransparentRegion);
                     // reconfigure window manager
@@ -1023,15 +1026,17 @@
                     = givenContent.bottom = givenVisible.left = givenVisible.top
                     = givenVisible.right = givenVisible.bottom = 0;
             attachInfo.mTreeObserver.dispatchOnComputeInternalInsets(insets);
-            if (mCompatibilityInfo.mScalingRequired) {
-                insets.contentInsets.scale(appScale);
-                insets.visibleInsets.scale(appScale);
+            Rect contentInsets = insets.contentInsets;
+            Rect visibleInsets = insets.visibleInsets;
+            if (mTranslator != null) {
+                contentInsets = mTranslator.getTranslatedContentInsets(contentInsets);
+                visibleInsets = mTranslator.getTranslatedVisbileInsets(visibleInsets);
             }
             if (insetsPending || !mLastGivenInsets.equals(insets)) {
                 mLastGivenInsets.set(insets);
                 try {
                     sWindowSession.setInsets(mWindow, insets.mTouchableInsets,
-                            insets.contentInsets, insets.visibleInsets);
+                            contentInsets, visibleInsets);
                 } catch (RemoteException e) {
                 }
             }
@@ -1174,8 +1179,8 @@
             mCurScrollY = yoff;
             fullRedrawNeeded = true;
         }
-        float appScale = mCompatibilityInfo.mApplicationScale;
-        boolean scalingRequired = mCompatibilityInfo.mScalingRequired;
+        float appScale = mAttachInfo.mApplicationScale;
+        boolean scalingRequired = mAttachInfo.mScalingRequired;
 
         Rect dirty = mDirty;
         if (mUseGL) {
@@ -1194,8 +1199,8 @@
                     int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);
                     try {
                         canvas.translate(0, -yoff);
-                        if (scalingRequired) {
-                            canvas.scale(appScale, appScale);
+                        if (mTranslator != null) {
+                            mTranslator.translateCanvas(canvas);
                         }
                         mView.draw(canvas);
                         if (Config.DEBUG && ViewDebug.consistencyCheckEnabled) {
@@ -1246,7 +1251,6 @@
             int top = dirty.top;
             int right = dirty.right;
             int bottom = dirty.bottom;
-
             canvas = surface.lockCanvas(dirty);
 
             if (left != dirty.left || top != dirty.top || right != dirty.right ||
@@ -1302,8 +1306,8 @@
                 int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);
                 try {
                     canvas.translate(0, -yoff);
-                    if (scalingRequired) {
-                        canvas.scale(appScale, appScale);
+                    if (mTranslator != null) {
+                        mTranslator.translateCanvas(canvas);
                     }
                     mView.draw(canvas);
                 } finally {
@@ -1616,10 +1620,9 @@
             } else {
                 didFinish = event.getAction() == MotionEvent.ACTION_OUTSIDE;
             }
-            if (event != null && mCompatibilityInfo.mScalingRequired) {
-                event.scale(mCompatibilityInfo.mApplicationInvertedScale);
+            if (event != null && mTranslator != null) {
+                mTranslator.translateEventInScreenToAppWindow(event);
             }
-
             try {
                 boolean handled;
                 if (mView != null && mAdded && event != null) {
@@ -1711,6 +1714,7 @@
         case RESIZED:
             Rect coveredInsets = ((Rect[])msg.obj)[0];
             Rect visibleInsets = ((Rect[])msg.obj)[1];
+
             if (mWinFrame.width() == msg.arg1 && mWinFrame.height() == msg.arg2
                     && mPendingContentInsets.equals(coveredInsets)
                     && mPendingVisibleInsets.equals(visibleInsets)) {
@@ -1745,7 +1749,7 @@
                         if (mGlWanted && !mUseGL) {
                             initializeGL();
                             if (mGlCanvas != null) {
-                                float appScale = mCompatibilityInfo.mApplicationScale;
+                                float appScale = mAttachInfo.mApplicationScale;
                                 mGlCanvas.setViewport(
                                         (int) (mWidth * appScale), (int) (mHeight * appScale));
                             }
@@ -2379,18 +2383,16 @@
 
     private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
             boolean insetsPending) throws RemoteException {
+
+        float appScale = mAttachInfo.mApplicationScale;
         boolean restore = false;
-        float appScale = mCompatibilityInfo.mApplicationScale;
-        boolean scalingRequired = mCompatibilityInfo.mScalingRequired;
-        if (params != null && !mCompatibilityInfo.mExpandable) {
+        if (params != null && mTranslator != null) {
             restore = true;
             params.backup();
-            adjustWindowAttributesForCompatibleMode(params);
+            mTranslator.translateWindowLayout(params);
         }
-        if (params != null && scalingRequired) {
-            if (!restore) params.backup();
-            restore = true;
-            params.scale(appScale);
+        if (params != null) {
+            if (DBG) Log.d(TAG, "WindowLayout in layoutWindow:" + params);
         }
         int relayoutResult = sWindowSession.relayout(
                 mWindow, params,
@@ -2401,44 +2403,16 @@
         if (restore) {
             params.restore();
         }
-        if (scalingRequired) {
-            float invertedScale = mCompatibilityInfo.mApplicationInvertedScale;
-            mPendingContentInsets.scale(invertedScale);
-            mPendingVisibleInsets.scale(invertedScale);
-            mWinFrame.scale(invertedScale);
+        
+        if (mTranslator != null) {
+            mTranslator.translateRectInScreenToAppWinFrame(mWinFrame);
+            mTranslator.translateRectInScreenToAppWindow(mPendingContentInsets);
+            mTranslator.translateRectInScreenToAppWindow(mPendingVisibleInsets);
         }
         return relayoutResult;
     }
 
     /**
-     * Adjust the window's layout parameter for compatibility mode. It replaces FILL_PARENT
-     * with the default window size, and centers if the window wanted to fill
-     * horizontally.
-     *
-     * @param attrs the window's layout params to adjust
-     */
-    private void adjustWindowAttributesForCompatibleMode(WindowManager.LayoutParams attrs) {
-        // fix app windows only
-        if (attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
-            DisplayMetrics metrics = mView.getContext().getResources().getDisplayMetrics();
-            // TODO: improve gravity logic
-            if (attrs.width == ViewGroup.LayoutParams.FILL_PARENT) {
-                attrs.width = metrics.widthPixels;
-                attrs.gravity |= Gravity.CENTER_HORIZONTAL;
-                mWindowAttributesChanged = attrs == mWindowAttributes;
-            }
-            if (attrs.height == ViewGroup.LayoutParams.FILL_PARENT) {
-                attrs.height = metrics.heightPixels;
-                attrs.gravity |= Gravity.TOP;
-                mWindowAttributesChanged = attrs == mWindowAttributes;
-            }
-            if (DEBUG_LAYOUT) {
-                Log.d(TAG, "Adjusted Attributes for compatibility : " + attrs);
-            }
-        }
-    }
-
-    /**
      * {@inheritDoc}
      */
     public void playSoundEffect(int effectId) {
@@ -2541,16 +2515,14 @@
                 + " visibleInsets=" + visibleInsets.toShortString()
                 + " reportDraw=" + reportDraw);
         Message msg = obtainMessage(reportDraw ? RESIZED_REPORT :RESIZED);
-        if (mCompatibilityInfo.mScalingRequired) {
-            float invertedScale = mCompatibilityInfo.mApplicationInvertedScale;
-            coveredInsets.scale(invertedScale);
-            visibleInsets.scale(invertedScale);
-            msg.arg1 = (int) (w * invertedScale);
-            msg.arg2 = (int) (h * invertedScale);
-        } else {
-            msg.arg1 = w;
-            msg.arg2 = h;
+        if (mTranslator != null) {
+            mTranslator.translateRectInScreenToAppWindow(coveredInsets);
+            mTranslator.translateRectInScreenToAppWindow(visibleInsets);
+            w *= mTranslator.applicationInvertedScale;
+            h *= mTranslator.applicationInvertedScale;
         }
+        msg.arg1 = w;
+        msg.arg2 = h;
         msg.obj = new Rect[] { new Rect(coveredInsets), new Rect(visibleInsets) };
         sendMessage(msg);
     }
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index e1c4687..bdb86d7 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -18,7 +18,6 @@
 
 import android.content.pm.ActivityInfo;
 import android.graphics.PixelFormat;
-import android.graphics.Rect;
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -484,6 +483,12 @@
          * {@hide} */
         public static final int FLAG_SHOW_WHEN_LOCKED = 0x00080000;
 
+        /** Window flag: special flag to let a window ignore the compatibility scaling.
+         * This is used by SurfaceView to create a window that does not scale the content.
+         *
+         * {@hide} */
+        public static final int FLAG_NO_COMPATIBILITY_SCALING = 0x00100000;
+
         /** Window flag: a special option intended for system dialogs.  When
          * this flag is set, the window will demand focus unconditionally when
          * it is created.
@@ -805,6 +810,7 @@
             screenOrientation = in.readInt();
         }
     
+        @SuppressWarnings({"PointlessBitwiseExpression"})
         public static final int LAYOUT_CHANGED = 1<<0;
         public static final int TYPE_CHANGED = 1<<1;
         public static final int FLAGS_CHANGED = 1<<2;
@@ -978,8 +984,9 @@
 
         /**
          * Scale the layout params' coordinates and size.
+         * @hide
          */
-        void scale(float scale) {
+        public void scale(float scale) {
             x *= scale;
             y *= scale;
             if (width > 0) {
@@ -997,14 +1004,13 @@
         void backup() {
             int[] backup = mCompatibilityParamsBackup;
             if (backup == null) {
-                // we backup 5 elements, x, y, width, height and gravity.
-                backup = mCompatibilityParamsBackup = new int[5];
+                // we backup 4 elements, x, y, width, height
+                backup = mCompatibilityParamsBackup = new int[4];
             }
             backup[0] = x;
             backup[1] = y;
             backup[2] = width;
             backup[3] = height;
-            backup[4] = gravity;
         }
 
         /**
@@ -1018,7 +1024,6 @@
                 y = backup[1];
                 width = backup[2];
                 height = backup[3];
-                gravity = backup[4];
             }
         }
 
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index 11de3e2..9a0f467 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -297,6 +297,10 @@
             b = tmp;
         }
 
+        if (a <= 0) {
+            return "";
+        }
+        
         if (length > a) {
             length = a;
         }
@@ -488,12 +492,12 @@
         } else {
             a = Selection.getSelectionStart(content);
             b = Selection.getSelectionEnd(content);
-            if (a >=0 && b>= 0 && a != b) {
-                if (b < a) {
-                    int tmp = a;
-                    a = b;
-                    b = tmp;
-                }
+            if (a < 0) a = 0;
+            if (b < 0) b = 0;
+            if (b < a) {
+                int tmp = a;
+                a = b;
+                b = tmp;
             }
         }
 
diff --git a/core/java/android/webkit/JWebCoreJavaBridge.java b/core/java/android/webkit/JWebCoreJavaBridge.java
index cbe337a..7c071be 100644
--- a/core/java/android/webkit/JWebCoreJavaBridge.java
+++ b/core/java/android/webkit/JWebCoreJavaBridge.java
@@ -227,7 +227,8 @@
     }
 
     private String getSignedPublicKey(int index, String challenge, String url) {
-        return Keystore.getInstance().generateKeyPair(index, challenge, url);
+        // generateKeyPair expects organizations which we don't have. Ignore url.
+        return Keystore.getInstance().generateKeyPair(index, challenge, null);
     }
 
     private native void nativeConstructor();
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 2d8950e..186e1d1 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1759,9 +1759,6 @@
     private Rect sendOurVisibleRect() {
         Rect rect = new Rect();
         calcOurContentVisibleRect(rect);
-        if (mFindIsUp) {
-            rect.bottom -= viewToContent(FIND_HEIGHT);
-        }
         // Rect.equals() checks for null input.
         if (!rect.equals(mLastVisibleRectSent)) {
             Point pos = new Point(rect.left, rect.top);
@@ -1772,6 +1769,11 @@
         Rect globalRect = new Rect();
         if (getGlobalVisibleRect(globalRect)
                 && !globalRect.equals(mLastGlobalRect)) {
+            if (DebugFlags.WEB_VIEW) {
+                Log.v(LOGTAG, "sendOurVisibleRect=(" + globalRect.left + ","
+                        + globalRect.top + ",r=" + globalRect.right + ",b="
+                        + globalRect.bottom);
+            }
             // TODO: the global offset is only used by windowRect()
             // in ChromeClientAndroid ; other clients such as touch
             // and mouse events could return view + screen relative points.
@@ -1786,6 +1788,9 @@
         Point p = new Point();
         getGlobalVisibleRect(r, p);
         r.offset(-p.x, -p.y);
+        if (mFindIsUp) {
+            r.bottom -= FIND_HEIGHT;
+        }
     }
 
     // Sets r to be our visible rectangle in content coordinates
@@ -3006,7 +3011,8 @@
             mTextGeneration = 0;
         }
         mWebTextView.setTextSize(contentToView(nativeFocusCandidateTextSize()));
-        Rect visibleRect = sendOurVisibleRect();
+        Rect visibleRect = new Rect();
+        calcOurContentVisibleRect(visibleRect);
         // Note that sendOurVisibleRect calls viewToContent, so the coordinates
         // should be in content coordinates.
         Rect bounds = nativeFocusCandidateNodeBounds();
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index 1c66803..96cc2fd 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -80,6 +80,7 @@
  * @attr ref android.R.styleable#AutoCompleteTextView_dropDownSelector
  * @attr ref android.R.styleable#AutoCompleteTextView_dropDownAnchor
  * @attr ref android.R.styleable#AutoCompleteTextView_dropDownWidth
+ * @attr ref android.R.styleable#AutoCompleteTextView_dropDownHeight
  */
 public class AutoCompleteTextView extends EditText implements Filter.FilterListener {
     static final boolean DEBUG = false;
@@ -101,6 +102,7 @@
     private int mDropDownAnchorId;
     private View mDropDownAnchorView;  // view is retrieved lazily from id once needed
     private int mDropDownWidth;
+    private int mDropDownHeight;
 
     private Drawable mDropDownListHighlight;
 
@@ -166,6 +168,8 @@
         // (for full screen width) or WRAP_CONTENT (to match the width of the anchored view).
         mDropDownWidth = a.getLayoutDimension(R.styleable.AutoCompleteTextView_dropDownWidth,
                 ViewGroup.LayoutParams.WRAP_CONTENT);
+        mDropDownHeight = a.getLayoutDimension(R.styleable.AutoCompleteTextView_dropDownHeight,
+                ViewGroup.LayoutParams.WRAP_CONTENT);
 
         mHintResource = a.getResourceId(R.styleable.AutoCompleteTextView_completionHintView,
                 R.layout.simple_dropdown_hint);
@@ -254,6 +258,34 @@
     public void setDropDownWidth(int width) {
         mDropDownWidth = width;
     }
+
+    /**
+     * <p>Returns the current height for the auto-complete drop down list. This can
+     * be a fixed height, or {@link ViewGroup.LayoutParams#FILL_PARENT} to fill
+     * the screen, or {@link ViewGroup.LayoutParams#WRAP_CONTENT} to fit the height
+     * of the drop down's content.</p>
+     *
+     * @return the height for the drop down list
+     *
+     * @attr ref android.R.styleable#AutoCompleteTextView_dropDownHeight
+     */
+    public int getDropDownHeight() {
+        return mDropDownHeight;
+    }
+
+    /**
+     * <p>Sets the current height for the auto-complete drop down list. This can
+     * be a fixed height, or {@link ViewGroup.LayoutParams#FILL_PARENT} to fill
+     * the screen, or {@link ViewGroup.LayoutParams#WRAP_CONTENT} to fit the height
+     * of the drop down's content.</p>
+     *
+     * @param height the height to use
+     *
+     * @attr ref android.R.styleable#AutoCompleteTextView_dropDownHeight
+     */
+    public void setDropDownHeight(int height) {
+        mDropDownHeight = height;
+    }
     
     /**
      * <p>Returns the id for the view that the auto-complete drop down list is anchored to.</p>
@@ -571,7 +603,7 @@
         if (isPopupShowing()) {
             // 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 (keyCode == KeyEvent.KEYCODE_BACK) {
+            if (keyCode == KeyEvent.KEYCODE_BACK && !mDropDownAlwaysVisible) {
                 dismissDropDown();
                 return true;
             }
@@ -621,7 +653,7 @@
                     // event to prevent focus from moving.
                     clearListSelection();
                     mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
-                    mPopup.update();
+                    showDropDown();
                     return true;
                 } else {
                     // WARNING: Please read the comment where mListSelectionHidden
@@ -641,7 +673,7 @@
                     // by ensuring it has focus and getting its window out
                     // of touch mode.
                     mDropDownList.requestFocusFromTouch();
-                    mPopup.update();
+                    showDropDown();
 
                     switch (keyCode) {
                         // avoid passing the focus from the text view to the
@@ -741,7 +773,7 @@
         } else {
             // drop down is automatically dismissed when enough characters
             // are deleted from the text view
-            dismissDropDown();
+            if (!mDropDownAlwaysVisible) dismissDropDown();
             if (mFilter != null) {
                 mFilter.filter(null);
             }
@@ -882,7 +914,7 @@
             }
         }
 
-        if (mDropDownDismissedOnCompletion) {
+        if (mDropDownDismissedOnCompletion && !mDropDownAlwaysVisible) {
             dismissDropDown();
         }
     }
@@ -963,7 +995,7 @@
             if (hasFocus() && hasWindowFocus()) {
                 showDropDown();
             }
-        } else {
+        } else if (!mDropDownAlwaysVisible) {
             dismissDropDown();
         }
     }
@@ -972,7 +1004,7 @@
     public void onWindowFocusChanged(boolean hasWindowFocus) {
         super.onWindowFocusChanged(hasWindowFocus);
         performValidation();
-        if (!hasWindowFocus) {
+        if (!hasWindowFocus && !mDropDownAlwaysVisible) {
             dismissDropDown();
         }
     }
@@ -981,7 +1013,7 @@
     protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
         super.onFocusChanged(focused, direction, previouslyFocusedRect);
         performValidation();
-        if (!focused) {
+        if (!focused && !mDropDownAlwaysVisible) {
             dismissDropDown();
         }
     }
@@ -1038,8 +1070,13 @@
      */
     public void showDropDown() {
         int height = buildDropDown();
+
+        int widthSpec = 0;
+        int heightSpec = 0;
+
+        boolean noInputMethod = mPopup.getInputMethodMode() == PopupWindow.INPUT_METHOD_NOT_NEEDED;
+
         if (mPopup.isShowing()) {
-            int widthSpec;
             if (mDropDownWidth == ViewGroup.LayoutParams.FILL_PARENT) {
                 // The call to PopupWindow's update method below can accept -1 for any
                 // value you do not want to update.
@@ -1049,20 +1086,51 @@
             } else {
                 widthSpec = mDropDownWidth;
             }
+
+            if (mDropDownHeight == ViewGroup.LayoutParams.FILL_PARENT) {
+                // The call to PopupWindow's update method below can accept -1 for any
+                // value you do not want to update.
+                heightSpec = noInputMethod ? height : ViewGroup.LayoutParams.FILL_PARENT;
+                if (noInputMethod) {
+                    mPopup.setWindowLayoutMode(
+                            mDropDownWidth == ViewGroup.LayoutParams.FILL_PARENT ?
+                                    ViewGroup.LayoutParams.FILL_PARENT : 0, 0);
+                } else {
+                    mPopup.setWindowLayoutMode(
+                            mDropDownWidth == ViewGroup.LayoutParams.FILL_PARENT ?
+                                    ViewGroup.LayoutParams.FILL_PARENT : 0,
+                            ViewGroup.LayoutParams.FILL_PARENT);
+                }
+            } else if (mDropDownHeight == ViewGroup.LayoutParams.WRAP_CONTENT) {
+                heightSpec = height;
+            } else {
+                heightSpec = mDropDownHeight;
+            }
+
             mPopup.update(getDropDownAnchorView(), mDropDownHorizontalOffset,
-                    mDropDownVerticalOffset, widthSpec, height);
+                    mDropDownVerticalOffset, widthSpec, heightSpec);
         } else {
             if (mDropDownWidth == ViewGroup.LayoutParams.FILL_PARENT) {
-                mPopup.setWindowLayoutMode(ViewGroup.LayoutParams.FILL_PARENT, 0);
+                widthSpec = ViewGroup.LayoutParams.FILL_PARENT;
             } else {
-                mPopup.setWindowLayoutMode(0, 0);
                 if (mDropDownWidth == ViewGroup.LayoutParams.WRAP_CONTENT) {
                     mPopup.setWidth(getDropDownAnchorView().getWidth());
                 } else {
                     mPopup.setWidth(mDropDownWidth);
                 }
             }
-            mPopup.setHeight(height);
+
+            if (mDropDownHeight == ViewGroup.LayoutParams.FILL_PARENT) {
+                heightSpec = ViewGroup.LayoutParams.FILL_PARENT;
+            } else {
+                if (mDropDownHeight == ViewGroup.LayoutParams.WRAP_CONTENT) {
+                    mPopup.setHeight(height);
+                } else {
+                    mPopup.setHeight(mDropDownHeight);
+                }
+            }
+
+            mPopup.setWindowLayoutMode(widthSpec, heightSpec);
             mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
             mPopup.setOutsideTouchable(true);
             mPopup.setTouchInterceptor(new PopupTouchIntercepter());
@@ -1178,10 +1246,12 @@
         final int maxHeight = mPopup.getMaxAvailableHeight(
                 getDropDownAnchorView(), mDropDownVerticalOffset, ignoreBottomDecorations);
 
-        final int measuredHeight = mDropDownList.measureHeightOfChildren(MeasureSpec.UNSPECIFIED,
-                0, ListView.NO_POSITION, maxHeight - otherHeights, 2) + otherHeights;
+        if (mDropDownAlwaysVisible) {
+            return maxHeight;
+        }
 
-        return mDropDownAlwaysVisible ? maxHeight : measuredHeight;
+        return mDropDownList.measureHeightOfChildren(MeasureSpec.UNSPECIFIED,
+                0, ListView.NO_POSITION, maxHeight - otherHeights, 2) + otherHeights;
     }
 
     private View getHintView(Context context) {
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 6532125..f8a6f89 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -3264,9 +3264,13 @@
         if (mChoiceMode == CHOICE_MODE_MULTIPLE) {
             mCheckStates.put(position, value);
         } else {
-            boolean oldValue = mCheckStates.get(position, false);
+            // Clear the old value: if something was selected and value == false
+            // then it is unselected
             mCheckStates.clear();
-            if (!oldValue) {
+            // If value == true, select the appropriate position
+            // this may end up selecting the value we just cleared but this way
+            // we don't have to first to a get(position)
+            if (value) {
                 mCheckStates.put(position, true);
             }
         }
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 68764a5..0c2cd55 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -49,7 +49,7 @@
  */
 public class PopupWindow {
     /**
-     * Mode for {@link #setInputMethodMode(int): the requirements for the
+     * Mode for {@link #setInputMethodMode(int)}: the requirements for the
      * input method should be based on the focusability of the popup.  That is
      * if it is focusable than it needs to work with the input method, else
      * it doesn't.
@@ -57,16 +57,15 @@
     public static final int INPUT_METHOD_FROM_FOCUSABLE = 0;
     
     /**
-     * Mode for {@link #setInputMethodMode(int): this popup always needs to
+     * Mode for {@link #setInputMethodMode(int)}: this popup always needs to
      * work with an input method, regardless of whether it is focusable.  This
      * means that it will always be displayed so that the user can also operate
      * the input method while it is shown.
      */
-    
     public static final int INPUT_METHOD_NEEDED = 1;
     
     /**
-     * Mode for {@link #setInputMethodMode(int): this popup never needs to
+     * Mode for {@link #setInputMethodMode(int)}: this popup never needs to
      * work with an input method, regardless of whether it is focusable.  This
      * means that it will always be displayed to use as much space on the
      * screen as needed, regardless of whether this covers the input method.
@@ -823,6 +822,7 @@
         p.flags = computeFlags(p.flags);
         p.type = WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
         p.token = token;
+        p.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
         p.setTitle("PopupWindow:" + Integer.toHexString(hashCode()));
 
         return p;
@@ -990,7 +990,7 @@
         
         int bottomEdge = displayFrame.bottom;
         if (ignoreBottomDecorations) {
-            bottomEdge = WindowManagerImpl.getDefault().getDefaultDisplay().getHeight();
+            bottomEdge = anchor.getContext().getResources().getDisplayMetrics().heightPixels;
         }
         final int distanceToBottom = bottomEdge - (anchorPos[1] + anchor.getHeight()) - yOffset;
         final int distanceToTop = anchorPos[1] - displayFrame.top + yOffset;
@@ -1130,8 +1130,7 @@
             return;
         }
 
-        WindowManager.LayoutParams p = (WindowManager.LayoutParams)
-                mPopupView.getLayoutParams();
+        WindowManager.LayoutParams p = (WindowManager.LayoutParams) mPopupView.getLayoutParams();
 
         boolean update = force;
 
@@ -1218,8 +1217,7 @@
             registerForScrollChanged(anchor, xoff, yoff);
         }
 
-        WindowManager.LayoutParams p = (WindowManager.LayoutParams)
-                mPopupView.getLayoutParams();
+        WindowManager.LayoutParams p = (WindowManager.LayoutParams) mPopupView.getLayoutParams();
 
         if (updateDimension) {
             if (width == -1) {
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index 84cf2c8..955475e4 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -20,8 +20,15 @@
 
 import android.content.Context;
 import android.content.res.TypedArray;
+import android.content.res.Resources;
 import android.graphics.Rect;
 import android.util.AttributeSet;
+import android.util.SparseArray;
+import android.util.Poolable;
+import android.util.Pool;
+import android.util.Pools;
+import android.util.PoolableManager;
+import static android.util.Log.d;
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewDebug;
@@ -32,6 +39,8 @@
 import java.util.Comparator;
 import java.util.SortedSet;
 import java.util.TreeSet;
+import java.util.LinkedList;
+import java.util.HashSet;
 
 /**
  * A Layout where the positions of the children can be described in relation to each other or to the
@@ -55,6 +64,10 @@
  */
 @RemoteView
 public class RelativeLayout extends ViewGroup {
+    private static final String LOG_TAG = "RelativeLayout";
+
+    private static final boolean DEBUG_GRAPH = false;
+
     public static final int TRUE = -1;
 
     /**
@@ -142,7 +155,12 @@
     private final Rect mSelfBounds = new Rect();
     private int mIgnoreGravity;
 
-    private static SortedSet<View> mTopToBottomLeftToRightSet = null;
+    private SortedSet<View> mTopToBottomLeftToRightSet = null;
+    
+    private boolean mDirtyHierarchy;
+    private View[] mSortedHorizontalChildren = new View[0];
+    private View[] mSortedVerticalChildren = new View[0];
+    private final DependencyGraph mGraph = new DependencyGraph();
 
     public RelativeLayout(Context context) {
         super(context);
@@ -232,7 +250,54 @@
     }
 
     @Override
+    public void requestLayout() {
+        super.requestLayout();
+        mDirtyHierarchy = true;
+    }
+
+    private void sortChildren() {
+        int count = getChildCount();
+        if (mSortedVerticalChildren.length != count) mSortedVerticalChildren = new View[count];
+        if (mSortedHorizontalChildren.length != count) mSortedHorizontalChildren = new View[count];
+
+        final DependencyGraph graph = mGraph;
+        graph.clear();
+
+        for (int i = 0; i < count; i++) {
+            final View child = getChildAt(i);
+            graph.add(child);
+        }
+
+        if (DEBUG_GRAPH) {
+            d(LOG_TAG, "=== Sorted vertical children");
+            graph.log(getResources(), ABOVE, BELOW, ALIGN_BASELINE, ALIGN_TOP, ALIGN_BOTTOM);
+            d(LOG_TAG, "=== Sorted horizontal children");
+            graph.log(getResources(), LEFT_OF, RIGHT_OF, ALIGN_LEFT, ALIGN_RIGHT);
+        }
+
+        graph.getSortedViews(mSortedVerticalChildren, ABOVE, BELOW, ALIGN_BASELINE,
+                ALIGN_TOP, ALIGN_BOTTOM);
+        graph.getSortedViews(mSortedHorizontalChildren, LEFT_OF, RIGHT_OF, ALIGN_LEFT, ALIGN_RIGHT);
+
+        if (DEBUG_GRAPH) {
+            d(LOG_TAG, "=== Ordered list of vertical children");
+            for (View view : mSortedVerticalChildren) {
+                DependencyGraph.printViewId(getResources(), view);
+            }
+            d(LOG_TAG, "=== Ordered list of horizontal children");
+            for (View view : mSortedHorizontalChildren) {
+                DependencyGraph.printViewId(getResources(), view);
+            }
+        }        
+    }
+
+    @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        if (mDirtyHierarchy) {
+            mDirtyHierarchy = false;
+            sortChildren();
+        }
+
         int myWidth = -1;
         int myHeight = -1;
 
@@ -261,7 +326,6 @@
             height = myHeight;
         }
 
-        int len = this.getChildCount();
         mHasBaselineAlignedChild = false;
 
         View ignore = null;
@@ -279,13 +343,29 @@
             ignore = findViewById(mIgnoreGravity);
         }
 
-        for (int i = 0; i < len; i++) {
-            View child = getChildAt(i);
+        View[] views = mSortedVerticalChildren;
+        int count = views.length;
+        for (int i = 0; i < count; i++) {
+            View child = views[i];
             if (child.getVisibility() != GONE) {
                 LayoutParams params = (LayoutParams) child.getLayoutParams();
-                applySizeRules(params, myWidth, myHeight);
+
+                applyHorizontalSizeRules(params, myWidth);
+                measureChildHorizontal(child, params, myWidth);
+                positionChildHorizontal(child, params, myWidth);
+            }
+        }
+
+        views = mSortedHorizontalChildren;
+        count = views.length;
+        for (int i = 0; i < count; i++) {
+            View child = views[i];
+            if (child.getVisibility() != GONE) {
+                LayoutParams params = (LayoutParams) child.getLayoutParams();
+                
+                applyVerticalSizeRules(params, myHeight);
                 measureChild(child, params, myWidth, myHeight);
-                positionChild(child, params, myWidth, myHeight);
+                positionChildVertical(child, params, myHeight);
 
                 if (widthMode != MeasureSpec.EXACTLY) {
                     width = Math.max(width, params.mRight);
@@ -307,15 +387,15 @@
         }
 
         if (mHasBaselineAlignedChild) {
-            for (int i = 0; i < len; i++) {
+            for (int i = 0; i < count; i++) {
                 View child = getChildAt(i);
                 if (child.getVisibility() != GONE) {
                     LayoutParams params = (LayoutParams) child.getLayoutParams();
                     alignBaseline(child, params);
 
                     if (child != ignore || verticalGravity) {
-                    left = Math.min(left, params.mLeft - params.leftMargin);
-                    top = Math.min(top, params.mTop - params.topMargin);
+                        left = Math.min(left, params.mLeft - params.leftMargin);
+                        top = Math.min(top, params.mTop - params.topMargin);
                     }
 
                     if (child != ignore || horizontalGravity) {
@@ -362,7 +442,7 @@
             final int horizontalOffset = contentBounds.left - left;
             final int verticalOffset = contentBounds.top - top;
             if (horizontalOffset != 0 || verticalOffset != 0) {
-                for (int i = 0; i < len; i++) {
+                for (int i = 0; i < count; i++) {
                     View child = getChildAt(i);
                     if (child.getVisibility() != GONE && child != ignore) {
                         LayoutParams params = (LayoutParams) child.getLayoutParams();
@@ -416,9 +496,7 @@
      * @param myWidth Width of the the RelativeLayout
      * @param myHeight Height of the RelativeLayout
      */
-    private void measureChild(View child, LayoutParams params, int myWidth,
-            int myHeight) {
-
+    private void measureChild(View child, LayoutParams params, int myWidth, int myHeight) {
         int childWidthMeasureSpec = getChildMeasureSpec(params.mLeft,
                 params.mRight, params.width,
                 params.leftMargin, params.rightMargin,
@@ -432,6 +510,16 @@
         child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
     }
 
+    private void measureChildHorizontal(View child, LayoutParams params, int myWidth) {
+        int childWidthMeasureSpec = getChildMeasureSpec(params.mLeft,
+                params.mRight, params.width,
+                params.leftMargin, params.rightMargin,
+                mPaddingLeft, mPaddingRight,
+                myWidth);
+        int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+        child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+    }
+
     /**
      * Get a measure spec that accounts for all of the constraints on this view.
      * This includes size contstraints imposed by the RelativeLayout as well as
@@ -511,19 +599,7 @@
         return MeasureSpec.makeMeasureSpec(childSpecSize, childSpecMode);
     }
 
-    /**
-     * After the child has been measured, assign it a position. Some views may
-     * already have final values for l,t,r,b. Others may have one or both edges
-     * unfixed (i.e. set to -1) in each dimension. These will get positioned
-     * based on which edge is fixed, the view's desired dimension, and whether
-     * or not it is centered.
-     *
-     * @param child Child to position
-     * @param params LayoutParams associated with child
-     * @param myWidth Width of the the RelativeLayout
-     * @param myHeight Height of the RelativeLayout
-     */
-    private void positionChild(View child, LayoutParams params, int myWidth, int myHeight) {
+    private void positionChildHorizontal(View child, LayoutParams params, int myWidth) {
         int[] rules = params.getRules();
 
         if (params.mLeft < 0 && params.mRight >= 0) {
@@ -541,6 +617,10 @@
                 params.mRight = params.mLeft + child.getMeasuredWidth();
             }
         }
+    }
+
+    private void positionChildVertical(View child, LayoutParams params, int myHeight) {
+        int[] rules = params.getRules();
 
         if (params.mTop < 0 && params.mBottom >= 0) {
             // Bottom is fixed, but top varies
@@ -559,17 +639,7 @@
         }
     }
 
-    /**
-     * Set l,t,r,b values in the LayoutParams for one view based on its layout rules.
-     * Big assumption #1: All antecedents of this view have been sized & positioned
-     * Big assumption #2: The dimensions of the parent view (the RelativeLayout)
-     * are already known if they are needed.
-     *
-     * @param childParams LayoutParams for the view being positioned
-     * @param myWidth Width of the the RelativeLayout
-     * @param myHeight Height of the RelativeLayout
-     */
-    private void applySizeRules(LayoutParams childParams, int myWidth, int myHeight) {
+    private void applyHorizontalSizeRules(LayoutParams childParams, int myWidth) {
         int[] rules = childParams.getRules();
         RelativeLayout.LayoutParams anchorParams;
 
@@ -629,6 +699,11 @@
                 // FIXME uh oh...
             }
         }
+    }
+
+    private void applyVerticalSizeRules(LayoutParams childParams, int myHeight) {
+        int[] rules = childParams.getRules();
+        RelativeLayout.LayoutParams anchorParams;
 
         childParams.mTop = -1;
         childParams.mBottom = -1;
@@ -691,18 +766,16 @@
     private View getRelatedView(int[] rules, int relation) {
         int id = rules[relation];
         if (id != 0) {
-            View v = findViewById(id);
-            if (v == null) {
-                return null;
-            }
+            DependencyGraph.Node node = mGraph.mNodes.get(id);
+            if (node == null) return null;
+            View v = node.view;
 
             // Find the first non-GONE view up the chain
             while (v.getVisibility() == View.GONE) {
                 rules = ((LayoutParams) v.getLayoutParams()).getRules();
-                v = v.findViewById(rules[relation]);
-                if (v == null) {
-                    return null;
-                }
+                node = mGraph.mNodes.get((rules[relation]));
+                if (node == null) return null;
+                v = node.view;
             }
 
             return v;
@@ -1033,4 +1106,265 @@
             return mRules;
         }
     }
+
+    private static class DependencyGraph {
+        /**
+         * List of nodes in the graph. Each node is identified by its
+         * view id (see View#getId()).
+         */
+        private SparseArray<Node> mNodes = new SparseArray<Node>();
+
+        /**
+         * Temporary data structure used to build the list of roots
+         * for this graph.
+         */
+        private LinkedList<Node> mRoots = new LinkedList<Node>();
+
+        /**
+         * Clears the graph.
+         */
+        void clear() {
+            final SparseArray<Node> nodes = mNodes;
+            final int count = nodes.size();
+
+            for (int i = 0; i < count; i++) {
+                nodes.valueAt(i).release();
+            }
+            nodes.clear();
+
+            mRoots.clear();
+        }
+
+        /**
+         * Adds a view to the graph.
+         *
+         * @param view The view to be added as a node to the graph.
+         */
+        void add(View view) {
+            mNodes.put(view.getId(), Node.acquire(view));
+        }
+
+        /**
+         * Builds a sorted list of views. The sorting order depends on the dependencies
+         * between the view. For instance, if view C needs view A to be processed first
+         * and view A needs view B to be processed first, the dependency graph
+         * is: B -> A -> C. The sorted array will contain views B, A and C in this order.
+         *
+         * @param sorted The sorted list of views. The length of this array must
+         *        be equal to getChildCount().
+         * @param rules The list of rules to take into account.
+         */
+        void getSortedViews(View[] sorted, int... rules) {
+            final LinkedList<Node> roots = findRoots(rules);
+            int index = 0;
+
+            while (roots.size() > 0) {
+                final Node node = roots.removeFirst();
+                final View view = node.view;
+                final int key = view.getId();
+
+                sorted[index++] = view;
+
+                final HashSet<Node> dependents = node.dependents;
+                for (Node dependent : dependents) {
+                    final SparseArray<Node> dependencies = dependent.dependencies;
+
+                    dependencies.remove(key);
+                    if (dependencies.size() == 0) {
+                        roots.add(dependent);
+                    }
+                }
+            }
+
+            if (index < sorted.length) {
+                throw new IllegalStateException("Circular dependencies cannot exist"
+                        + " in RelativeLayout");
+            }
+        }
+
+        /**
+         * Finds the roots of the graph. A root is a node with no dependency and
+         * with [0..n] dependents.
+         *
+         * @param rulesFilter The list of rules to consider when building the
+         *        dependencies
+         *
+         * @return A list of node, each being a root of the graph
+         */
+        private LinkedList<Node> findRoots(int[] rulesFilter) {
+            final SparseArray<Node> nodes = mNodes;
+            final int count = nodes.size();
+
+            // Find roots can be invoked several times, so make sure to clear
+            // all dependents and dependencies before running the algorithm
+            for (int i = 0; i < count; i++) {
+                final Node node = nodes.valueAt(i);
+                node.dependents.clear();
+                node.dependencies.clear();
+            }
+
+            // Builds up the dependents and dependencies for each node of the graph
+            for (int i = 0; i < count; i++) {
+                final Node node = nodes.valueAt(i);
+
+                final LayoutParams layoutParams = (LayoutParams) node.view.getLayoutParams();
+                final int[] rules = layoutParams.mRules;
+                final int rulesCount = rulesFilter.length;
+
+                // Look only the the rules passed in parameter, this way we build only the
+                // dependencies for a specific set of rules
+                for (int j = 0; j < rulesCount; j++) {
+                    final int rule = rules[rulesFilter[j]];
+                    if (rule > 0) {
+                        // The node this node depends on
+                        final Node dependency = nodes.get(rule);
+                        if (dependency == node) {
+                            throw new IllegalStateException("A view cannot have a dependency" +
+                                    " on itself");
+                        }
+                        // Add the current node as a dependent
+                        dependency.dependents.add(node);
+                        // Add a dependency to the current node
+                        node.dependencies.put(rule, dependency);
+                    }
+                }
+            }
+
+            final LinkedList<Node> roots = mRoots;
+            roots.clear();
+
+            // Finds all the roots in the graph: all nodes with no dependencies
+            for (int i = 0; i < count; i++) {
+                final Node node = nodes.valueAt(i);
+                if (node.dependencies.size() == 0) roots.add(node);
+            }
+
+            return roots;
+        }
+
+        /**
+         * Prints the dependency graph for the specified rules.
+         *
+         * @param resources The context's resources to print the ids.
+         * @param rules The list of rules to take into account.
+         */
+        void log(Resources resources, int... rules) {
+            final LinkedList<Node> roots = findRoots(rules);
+            for (Node node : roots) {
+                printNode(resources, node);
+            }
+        }
+
+        static void printViewId(Resources resources, View view) {
+            if (view.getId() != View.NO_ID) {
+                d(LOG_TAG, resources.getResourceEntryName(view.getId()));
+            } else {
+                d(LOG_TAG, "NO_ID");
+            }
+        }
+
+        private static void appendViewId(Resources resources, Node node, StringBuilder buffer) {
+            if (node.view.getId() != View.NO_ID) {
+                buffer.append(resources.getResourceEntryName(node.view.getId()));
+            } else {
+                buffer.append("NO_ID");
+            }
+        }
+
+        private static void printNode(Resources resources, Node node) {
+            if (node.dependents.size() == 0) {
+                printViewId(resources, node.view);
+            } else {
+                for (Node dependent : node.dependents) {
+                    StringBuilder buffer = new StringBuilder();
+                    appendViewId(resources, node, buffer);
+                    printdependents(resources, dependent, buffer);
+                }
+            }
+        }
+
+        private static void printdependents(Resources resources, Node node, StringBuilder buffer) {
+            buffer.append(" -> ");
+            appendViewId(resources, node, buffer);
+
+            if (node.dependents.size() == 0) {
+                d(LOG_TAG, buffer.toString());
+            } else {
+                for (Node dependent : node.dependents) {
+                    StringBuilder subBuffer = new StringBuilder(buffer);
+                    printdependents(resources, dependent, subBuffer);
+                }
+            }
+        }
+
+        /**
+         * A node in the dependency graph. A node is a view, its list of dependencies
+         * and its list of dependents.
+         *
+         * A node with no dependent is considered a root of the graph.
+         */
+        static class Node implements Poolable<Node> {
+            /**
+             * The view representing this node in the layout.
+             */
+            View view;
+
+            /**
+             * The list of dependents for this node; a dependent is a node
+             * that needs this node to be processed first.
+             */
+            final HashSet<Node> dependents = new HashSet<Node>();
+
+            /**
+             * The list of dependencies for this node.
+             */
+            final SparseArray<Node> dependencies = new SparseArray<Node>();
+
+            /*
+             * START POOL IMPLEMENTATION
+             */
+            private static final int POOL_LIMIT = 12;
+            private static final Pool<Node> sPool = Pools.synchronizedPool(
+                    Pools.finitePool(new PoolableManager<Node>() {
+                        public Node newInstance() {
+                            return new Node();
+                        }
+
+                        public void onAcquired(Node element) {
+                        }
+
+                        public void onReleased(Node element) {
+                        }
+                    }, POOL_LIMIT)
+            );
+
+            private Node mNext;
+
+            public void setNextPoolable(Node element) {
+                mNext = element;
+            }
+
+            public Node getNextPoolable() {
+                return mNext;
+            }
+
+            static Node acquire(View view) {
+                final Node node = sPool.acquire();
+                node.view = view;
+
+                return node;
+            }
+
+            void release() {
+                view = null;
+                dependents.clear();
+                dependencies.clear();
+
+                sPool.release(this);
+            }
+            /*
+             * END POOL IMPLEMENTATION
+             */
+        }
+    }
 }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 1678f9a..d8ed4f0 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3681,12 +3681,13 @@
 
     @Override
     protected boolean isPaddingOffsetRequired() {
-        return mShadowRadius != 0;
+        return mShadowRadius != 0 || mDrawables != null;
     }
 
     @Override
     protected int getLeftPaddingOffset() {
-        return (int) Math.min(0, mShadowDx - mShadowRadius);
+        return getCompoundPaddingLeft() - mPaddingLeft +
+                (int) Math.min(0, mShadowDx - mShadowRadius);
     }
 
     @Override
@@ -3701,7 +3702,8 @@
 
     @Override
     protected int getRightPaddingOffset() {
-        return (int) Math.max(0, mShadowDx + mShadowRadius);
+        return -(getCompoundPaddingRight() - mPaddingRight) +
+                (int) Math.max(0, mShadowDx + mShadowRadius);
     }
 
     @Override
@@ -6469,6 +6471,13 @@
         
         protected void onReceiveResult(int resultCode, Bundle resultData) {
             if (resultCode != InputMethodManager.RESULT_SHOWN) {
+                final int len = mText.length();
+                if (mNewStart > len) {
+                    mNewStart = len;
+                }
+                if (mNewEnd > len) {
+                    mNewEnd = len;
+                }
                 Selection.setSelection((Spannable)mText, mNewStart, mNewEnd);
             }
         }
@@ -6658,9 +6667,10 @@
             } else if (getLineCount() == 1) {
                 switch (mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
                     case Gravity.LEFT:
-                        return (mLayout.getLineRight(0) - mScrollX - (mRight - mLeft) -
-                                getCompoundPaddingLeft() - getCompoundPaddingRight()) /
-                                getHorizontalFadingEdgeLength();
+                        final int textWidth = (mRight - mLeft) - getCompoundPaddingLeft() -
+                                getCompoundPaddingRight();
+                        final float lineWidth = mLayout.getLineWidth(0);
+                        return (lineWidth - textWidth) / getHorizontalFadingEdgeLength();
                     case Gravity.RIGHT:
                         return 0.0f;
                     case Gravity.CENTER_HORIZONTAL:
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index ce32754..4bac593 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -37,6 +37,7 @@
     void notePhoneOff();
     void notePhoneSignalStrength(in SignalStrength signalStrength);
     void notePhoneDataConnectionState(int dataType, boolean hasData);
+    void noteAirplaneMode(boolean isAirplaneMode);
     void noteWifiOn(int uid);
     void noteWifiOff(int uid);
     void noteWifiRunning();
diff --git a/core/java/com/android/internal/backup/IBackupTransport.aidl b/core/java/com/android/internal/backup/IBackupTransport.aidl
index 84ed729..ec63528 100644
--- a/core/java/com/android/internal/backup/IBackupTransport.aidl
+++ b/core/java/com/android/internal/backup/IBackupTransport.aidl
@@ -54,63 +54,70 @@
     long requestBackupTime();
 
     /**
-     * Establish a connection to the back-end data repository, if necessary.  If the transport
-     * needs to initialize state that is not tied to individual applications' backup operations,
-     * this is where it should be done.
-     *
-     * @return Zero on success; a nonzero error code on failure.
-     */
-    int startSession();
-
-    /**
-     * Send one application's data to the backup destination.
+     * Send one application's data to the backup destination.  The transport may send
+     * the data immediately, or may buffer it.  After this is called, {@link #finishBackup}
+     * must be called to ensure the data is sent and recorded successfully.
      *
      * @param packageInfo The identity of the application whose data is being backed up.
      *   This specifically includes the signature list for the package.
      * @param data The data stream that resulted from invoking the application's
      *   BackupService.doBackup() method.  This may be a pipe rather than a file on
      *   persistent media, so it may not be seekable.
-     * @return Zero on success; a nonzero error code on failure.
+     * @return false if errors occurred (the backup should be aborted and rescheduled),
+     *   true if everything is OK so far (but {@link #finishBackup} must be called).
      */
-    int performBackup(in PackageInfo packageInfo, in ParcelFileDescriptor data);
+    boolean performBackup(in PackageInfo packageInfo, in ParcelFileDescriptor inFd);
+
+    /**
+     * Finish sending application data to the backup destination.  This must be
+     * called after {@link #performBackup} to ensure that all data is sent.  Only
+     * when this method returns true can the backup be assumed to have succeeded.
+     *
+     * @return false if errors occurred (the backup should be aborted and rescheduled),
+     *   true if everything is OK so far (but {@link #finishBackup} must be called).
+     */
+    boolean finishBackup();
 
     /**
      * Get the set of backups currently available over this transport.
      *
-     * @return Descriptions of the set of restore images available for this device.
+     * @return Descriptions of the set of restore images available for this device,
+     *   or null if an error occurred (the attempt should be rescheduled).
      **/
     RestoreSet[] getAvailableRestoreSets();
 
     /**
-     * Get the set of applications from a given restore image.
+     * Start restoring application data from backup.  After calling this function,
+     * alternate calls to {@link #nextRestorePackage} and {@link #nextRestoreData}
+     * to walk through the actual application data.
      *
      * @param token A backup token as returned by {@link #getAvailableRestoreSets}.
-     * @return An array of PackageInfo objects describing all of the applications
-     *   available for restore from this restore image.  This should include the list
-     *   of signatures for each package so that the Backup Manager can filter using that
-     *   information.
+     * @param packages List of applications to restore (if data is available).
+     *   Application data will be restored in the order given.
+     * @return false if errors occurred (the restore should be aborted and rescheduled),
+     *   true if everything is OK so far (go ahead and call {@link #nextRestorePackage}).
      */
-    PackageInfo[] getAppSet(int token);
+    boolean startRestore(long token, in PackageInfo[] packages);
 
     /**
-     * Retrieve one application's data from the backing store.
-     *
-     * @param token The backup record from which a restore is being requested.
-     * @param packageInfo The identity of the application whose data is being restored.
-     *   This must include the signature list for the package; it is up to the transport
-     *   to verify that the requested app's signatures match the saved backup record
-     *   because the transport cannot necessarily trust the client device.
-     * @param data An open, writable file into which the backup image should be stored.
-     * @return Zero on success; a nonzero error code on failure.
+     * Get the package name of the next application with data in the backup store.
+     * @return The name of one of the packages supplied to {@link #startRestore},
+     *   or "" (the empty string) if no more backup data is available,
+     *   or null if an error occurred (the restore should be aborted and rescheduled).
      */
-    int getRestoreData(int token, in PackageInfo packageInfo, in ParcelFileDescriptor data);
+    String nextRestorePackage();
 
     /**
-     * Terminate the backup session, closing files, freeing memory, and cleaning up whatever
-     * other state the transport required.
-     *
-     * @return Zero on success; a nonzero error code on failure.  Even on failure, the session
-     *         is torn down and must be restarted if another backup is attempted.
+     * Get the data for the application returned by {@link #nextRestorePackage}.
+     * @param data An open, writable file into which the backup data should be stored.
+     * @return false if errors occurred (the restore should be aborted and rescheduled),
+     *   true if everything is OK so far (go ahead and call {@link #nextRestorePackage}).
      */
-    int endSession();
+    boolean getRestoreData(in ParcelFileDescriptor outFd);
+
+    /**
+     * End a restore session (aborting any in-process data transfer as necessary),
+     * freeing any resources and connections used during the restore process.
+     */
+    void finishRestore();
 }
diff --git a/core/java/com/android/internal/backup/LocalTransport.java b/core/java/com/android/internal/backup/LocalTransport.java
index 3ef8666..0fbbb3f 100644
--- a/core/java/com/android/internal/backup/LocalTransport.java
+++ b/core/java/com/android/internal/backup/LocalTransport.java
@@ -33,11 +33,8 @@
     private Context mContext;
     private PackageManager mPackageManager;
     private File mDataDir = new File(Environment.getDownloadCacheDirectory(), "backup");
-    private FileFilter mDirFileFilter = new FileFilter() {
-        public boolean accept(File f) {
-            return f.isDirectory();
-        }
-    };
+    private PackageInfo[] mRestorePackages = null;
+    private int mRestorePackage = -1;  // Index into mRestorePackages
 
 
     public LocalTransport(Context context) {
@@ -51,21 +48,9 @@
         return 0;
     }
 
-    public int startSession() throws RemoteException {
-        if (DEBUG) Log.v(TAG, "session started");
-        mDataDir.mkdirs();
-        return 0;
-    }
-
-    public int endSession() throws RemoteException {
-        if (DEBUG) Log.v(TAG, "session ended");
-        return 0;
-    }
-
-    public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor data)
+    public boolean performBackup(PackageInfo packageInfo, ParcelFileDescriptor data)
             throws RemoteException {
         if (DEBUG) Log.v(TAG, "performBackup() pkg=" + packageInfo.packageName);
-        int err = 0;
 
         File packageDir = new File(mDataDir, packageInfo.packageName);
         packageDir.mkdirs();
@@ -101,9 +86,8 @@
                     try {
                         entity.write(buf, 0, dataSize);
                     } catch (IOException e) {
-                        Log.e(TAG, "Unable to update key file "
-                                + entityFile.getAbsolutePath());
-                        err = -1;
+                        Log.e(TAG, "Unable to update key file " + entityFile.getAbsolutePath());
+                        return false;
                     } finally {
                         entity.close();
                     }
@@ -111,14 +95,17 @@
                     entityFile.delete();
                 }
             }
+            return true;
         } catch (IOException e) {
             // oops, something went wrong.  abort the operation and return error.
-            Log.v(TAG, "Exception reading backup input:");
-            e.printStackTrace();
-            err = -1;
+            Log.v(TAG, "Exception reading backup input:", e);
+            return false;
         }
+    }
 
-        return err;
+    public boolean finishBackup() throws RemoteException {
+        if (DEBUG) Log.v(TAG, "finishBackup()");
+        return true;
     }
 
     // Restore handling
@@ -129,65 +116,66 @@
         return array;
     }
 
-    public PackageInfo[] getAppSet(int token) throws android.os.RemoteException {
-        if (DEBUG) Log.v(TAG, "getting app set " + token);
-        // the available packages are the extant subdirs of mDatadir
-        File[] packageDirs = mDataDir.listFiles(mDirFileFilter);
-        ArrayList<PackageInfo> packages = new ArrayList<PackageInfo>();
-        for (File dir : packageDirs) {
-            try {
-                PackageInfo pkg = mPackageManager.getPackageInfo(dir.getName(),
-                        PackageManager.GET_SIGNATURES);
-                if (pkg != null) {
-                    packages.add(pkg);
-                }
-            } catch (NameNotFoundException e) {
-                // restore set contains data for a package not installed on the
-                // phone -- just ignore it.
-            }
-        }
-
-        if (DEBUG) {
-            Log.v(TAG, "Built app set of " + packages.size() + " entries:");
-            for (PackageInfo p : packages) {
-                Log.v(TAG, "    + " + p.packageName);
-            }
-        }
-
-        PackageInfo[] result = new PackageInfo[packages.size()];
-        return packages.toArray(result);
+    public boolean startRestore(long token, PackageInfo[] packages) {
+        if (DEBUG) Log.v(TAG, "start restore " + token);
+        mRestorePackages = packages;
+        mRestorePackage = -1;
+        return true;
     }
 
-    public int getRestoreData(int token, PackageInfo packageInfo, ParcelFileDescriptor outFd)
-            throws android.os.RemoteException {
-        if (DEBUG) Log.v(TAG, "getting restore data " + token + " : " + packageInfo.packageName);
-        // we only support one hardcoded restore set
-        if (token != 0) return -1;
+    public String nextRestorePackage() {
+        if (mRestorePackages == null) throw new IllegalStateException("startRestore not called");
+        while (++mRestorePackage < mRestorePackages.length) {
+            String name = mRestorePackages[mRestorePackage].packageName;
+            if (new File(mDataDir, name).isDirectory()) {
+                if (DEBUG) Log.v(TAG, "  nextRestorePackage() = " + name);
+                return name;
+            }
+        }
 
-        // the data for a given package is at a known location
-        File packageDir = new File(mDataDir, packageInfo.packageName);
+        if (DEBUG) Log.v(TAG, "  no more packages to restore");
+        return "";
+    }
+
+    public boolean getRestoreData(ParcelFileDescriptor outFd) {
+        if (mRestorePackages == null) throw new IllegalStateException("startRestore not called");
+        if (mRestorePackage < 0) throw new IllegalStateException("nextRestorePackage not called");
+        File packageDir = new File(mDataDir, mRestorePackages[mRestorePackage].packageName);
 
         // The restore set is the concatenation of the individual record blobs,
         // each of which is a file in the package's directory
         File[] blobs = packageDir.listFiles();
-        int err = 0;
-        if (blobs != null && blobs.length > 0) {
-            BackupDataOutput out = new BackupDataOutput(outFd.getFileDescriptor());
-            try {
-                for (File f : blobs) {
-                    FileInputStream in = new FileInputStream(f);
+        if (blobs == null) {
+            Log.e(TAG, "Error listing directory: " + packageDir);
+            return false;  // nextRestorePackage() ensures the dir exists, so this is an error
+        }
+
+        // We expect at least some data if the directory exists in the first place
+        if (DEBUG) Log.v(TAG, "  getRestoreData() found " + blobs.length + " key files");
+        BackupDataOutput out = new BackupDataOutput(outFd.getFileDescriptor());
+        try {
+            for (File f : blobs) {
+                FileInputStream in = new FileInputStream(f);
+                try {
                     int size = (int) f.length();
                     byte[] buf = new byte[size];
                     in.read(buf);
                     String key = new String(Base64.decode(f.getName()));
+                    if (DEBUG) Log.v(TAG, "    ... key=" + key + " size=" + size);
                     out.writeEntityHeader(key, size);
                     out.writeEntityData(buf, size);
+                } finally {
+                    in.close();
                 }
-            } catch (Exception e) {
-                Log.e(TAG, "Unable to read backup records");
-                err = -1;
             }
+            return true;
+        } catch (IOException e) {
+            Log.e(TAG, "Unable to read backup records", e);
+            return false;
         }
-        return err;
+    }
+
+    public void finishRestore() {
+        if (DEBUG) Log.v(TAG, "finishRestore()");
     }
 }
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 16a3bad..fc4a9c4 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -191,6 +191,8 @@
     private final Map<String, KernelWakelockStats> mProcWakelockFileStats = 
             new HashMap<String, KernelWakelockStats>();
 
+    private HashMap<String, Integer> mUidCache = new HashMap<String, Integer>();
+    
     // For debugging
     public BatteryStatsImpl() {
         mFile = mBackupFile = null;
@@ -714,6 +716,10 @@
             }
         }
 
+        boolean isRunningLocked() {
+            return mNesting > 0;
+        }
+
         void stopRunningLocked(BatteryStatsImpl stats) {
             // Ignore attempt to stop a timer that isn't running
             if (mNesting == 0) {
@@ -984,11 +990,11 @@
     }
 
     public void noteStartGps(int uid) {
-        mUidStats.get(uid).noteStartGps();
+        getUidStatsLocked(uid).noteStartGps();
     }
     
     public void noteStopGps(int uid) {
-        mUidStats.get(uid).noteStopGps();
+        getUidStatsLocked(uid).noteStopGps();
     }
 
     public void noteScreenOnLocked() {
@@ -1032,10 +1038,7 @@
     }
     
     public void noteUserActivityLocked(int uid, int event) {
-        Uid u = mUidStats.get(uid);
-        if (u != null) {
-            u.noteUserActivityLocked(event);
-        }
+        getUidStatsLocked(uid).noteUserActivityLocked(event);
     }
     
     public void notePhoneOnLocked() {
@@ -1051,7 +1054,24 @@
             mPhoneOnTimer.stopRunningLocked(this);
         }
     }
-    
+
+    public void noteAirplaneModeLocked(boolean isAirplaneMode) {
+        final int bin = mPhoneSignalStrengthBin;
+        if (bin >= 0) {
+            if (!isAirplaneMode) {
+                if (!mPhoneSignalStrengthsTimer[bin].isRunningLocked()) {
+                    mPhoneSignalStrengthsTimer[bin].startRunningLocked(this);
+                }
+            } else {
+                for (int i = 0; i < NUM_SIGNAL_STRENGTH_BINS; i++) {
+                    while (mPhoneSignalStrengthsTimer[i].isRunningLocked()) {
+                        mPhoneSignalStrengthsTimer[i].stopRunningLocked(this);
+                    }
+                }
+            }
+        }
+    }
+
     public void notePhoneSignalStrengthLocked(SignalStrength signalStrength) {
         // Bin the strength.
         int bin;
@@ -1115,16 +1135,10 @@
         }
         if (mWifiOnUid != uid) {
             if (mWifiOnUid >= 0) {
-                Uid u = mUidStats.get(mWifiOnUid);
-                if (u != null) {
-                    u.noteWifiTurnedOffLocked();
-                }
+                getUidStatsLocked(mWifiOnUid).noteWifiTurnedOffLocked();
             }
             mWifiOnUid = uid;
-            Uid u = mUidStats.get(uid);
-            if (u != null) {
-                u.noteWifiTurnedOnLocked();
-            }
+            getUidStatsLocked(uid).noteWifiTurnedOnLocked();
         }
     }
     
@@ -1134,10 +1148,7 @@
             mWifiOnTimer.stopRunningLocked(this);
         }
         if (mWifiOnUid >= 0) {
-            Uid u = mUidStats.get(mWifiOnUid);
-            if (u != null) {
-                u.noteWifiTurnedOffLocked();
-            }
+            getUidStatsLocked(mWifiOnUid).noteWifiTurnedOffLocked();
             mWifiOnUid = -1;
         }
     }
@@ -1147,10 +1158,7 @@
             mAudioOn = true;
             mAudioOnTimer.startRunningLocked(this);
         }
-        Uid u = mUidStats.get(uid);
-        if (u != null) {
-            u.noteAudioTurnedOnLocked();
-        }
+        getUidStatsLocked(uid).noteAudioTurnedOnLocked();
     }
     
     public void noteAudioOffLocked(int uid) {
@@ -1158,10 +1166,7 @@
             mAudioOn = false;
             mAudioOnTimer.stopRunningLocked(this);
         }
-        Uid u = mUidStats.get(uid);
-        if (u != null) {
-            u.noteAudioTurnedOffLocked();
-        }
+        getUidStatsLocked(uid).noteAudioTurnedOffLocked();
     }
 
     public void noteVideoOnLocked(int uid) {
@@ -1169,10 +1174,7 @@
             mVideoOn = true;
             mVideoOnTimer.startRunningLocked(this);
         }
-        Uid u = mUidStats.get(uid);
-        if (u != null) {
-            u.noteVideoTurnedOnLocked();
-        }
+        getUidStatsLocked(uid).noteVideoTurnedOnLocked();
     }
     
     public void noteVideoOffLocked(int uid) {
@@ -1180,10 +1182,7 @@
             mVideoOn = false;
             mVideoOnTimer.stopRunningLocked(this);
         }
-        Uid u = mUidStats.get(uid);
-        if (u != null) {
-            u.noteVideoTurnedOffLocked();
-        }
+        getUidStatsLocked(uid).noteVideoTurnedOffLocked();
     }
 
     public void noteWifiRunningLocked() {
@@ -1215,45 +1214,27 @@
     }
     
     public void noteFullWifiLockAcquiredLocked(int uid) {
-        Uid u = mUidStats.get(uid);
-        if (u != null) {
-            u.noteFullWifiLockAcquiredLocked();
-        }
+        getUidStatsLocked(uid).noteFullWifiLockAcquiredLocked();
     }
 
     public void noteFullWifiLockReleasedLocked(int uid) {
-        Uid u = mUidStats.get(uid);
-        if (u != null) {
-            u.noteFullWifiLockReleasedLocked();
-        }
+        getUidStatsLocked(uid).noteFullWifiLockReleasedLocked();
     }
 
     public void noteScanWifiLockAcquiredLocked(int uid) {
-        Uid u = mUidStats.get(uid);
-        if (u != null) {
-            u.noteScanWifiLockAcquiredLocked();
-        }
+        getUidStatsLocked(uid).noteScanWifiLockAcquiredLocked();
     }
 
     public void noteScanWifiLockReleasedLocked(int uid) {
-        Uid u = mUidStats.get(uid);
-        if (u != null) {
-            u.noteScanWifiLockReleasedLocked();
-        }
+        getUidStatsLocked(uid).noteScanWifiLockReleasedLocked();
     }
 
     public void noteWifiMulticastEnabledLocked(int uid) {
-        Uid u = mUidStats.get(uid);
-        if (u != null) {
-            u.noteWifiMulticastEnabledLocked();
-        }
+        getUidStatsLocked(uid).noteWifiMulticastEnabledLocked();
     }
 
     public void noteWifiMulticastDisabledLocked(int uid) {
-        Uid u = mUidStats.get(uid);
-        if (u != null) {
-            u.noteWifiMulticastDisabledLocked();
-        }
+        getUidStatsLocked(uid).noteWifiMulticastDisabledLocked();
     }
 
     @Override public long getScreenOnTime(long batteryRealtime, int which) {
@@ -2839,7 +2820,7 @@
     public void removeUidStatsLocked(int uid) {
         mUidStats.remove(uid);
     }
-    
+
     /**
      * Retrieve the statistics object for a particular process, creating
      * if needed.
@@ -2850,6 +2831,26 @@
     }
 
     /**
+     * Retrieve the statistics object for a particular process, given
+     * the name of the process.
+     * @param name process name
+     * @return the statistics object for the process
+     */
+    public Uid.Proc getProcessStatsLocked(String name) {
+        int uid;
+        if (mUidCache.containsKey(name)) {
+            uid = mUidCache.get(name);
+        } else {
+            // TODO: Find the actual uid from /proc/pid/status. For now use the hashcode of the
+            // process name
+            uid = name.hashCode();
+            mUidCache.put(name, uid);
+        }
+        Uid u = getUidStatsLocked(uid);
+        return u.getProcessStatsLocked(name);
+    }
+
+    /**
      * Retrieve the statistics object for a particular process, creating
      * if needed.
      */
diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java
index a37bf6e..4a8d8b1 100644
--- a/core/java/com/android/internal/os/PowerProfile.java
+++ b/core/java/com/android/internal/os/PowerProfile.java
@@ -219,12 +219,12 @@
     public double getAveragePower(String type, int level) {
         if (sPowerMap.containsKey(type)) {
             Object data = sPowerMap.get(type);
-            if (data instanceof double[]) {
-                final double[] values = (double[]) data;
-                if (values.length > level) {
+            if (data instanceof Double[]) {
+                final Double[] values = (Double[]) data;
+                if (values.length > level && level >= 0) {
                     return values[level];
-                } else if (values.length < 0) {
-                    return values[0];
+                } else if (level < 0) {
+                    return 0;
                 } else {
                     return values[values.length - 1];
                 }
diff --git a/core/java/com/google/android/mms/pdu/PduPersister.java b/core/java/com/google/android/mms/pdu/PduPersister.java
index d2a41f1..74af7650 100644
--- a/core/java/com/google/android/mms/pdu/PduPersister.java
+++ b/core/java/com/google/android/mms/pdu/PduPersister.java
@@ -31,6 +31,7 @@
 import android.database.Cursor;
 import android.database.DatabaseUtils;
 import android.net.Uri;
+import android.provider.Telephony;
 import android.provider.Telephony.Mms;
 import android.provider.Telephony.MmsSms;
 import android.provider.Telephony.Threads;
@@ -54,6 +55,8 @@
 import java.util.Set;
 import java.util.Map.Entry;
 
+import com.google.android.mms.pdu.EncodedStringValue;
+
 /**
  * This class is the high-level manager of PDU storage.
  */
@@ -159,6 +162,7 @@
         Part.CONTENT_TYPE,
         Part.FILENAME,
         Part.NAME,
+        Part.TEXT
     };
 
     private static final int PART_COLUMN_ID                  = 0;
@@ -169,6 +173,7 @@
     private static final int PART_COLUMN_CONTENT_TYPE        = 5;
     private static final int PART_COLUMN_FILENAME            = 6;
     private static final int PART_COLUMN_NAME                = 7;
+    private static final int PART_COLUMN_TEXT                = 8;
 
     private static final HashMap<Uri, Integer> MESSAGE_BOX_MAP;
     // These map are used for convenience in persist() and load().
@@ -414,26 +419,36 @@
                     ByteArrayOutputStream baos = new ByteArrayOutputStream();
                     InputStream is = null;
 
-                    try {
-                        is = mContentResolver.openInputStream(partURI);
+                    // Store simple string values directly in the database instead of an
+                    // external file.  This makes the text searchable and retrieval slightly
+                    // faster.
+                    if ("text/plain".equals(type) || "application/smil".equals(type)) {
+                        String text = c.getString(PART_COLUMN_TEXT);
+                        byte [] blob = new EncodedStringValue(text).getTextString();
+                        baos.write(blob, 0, blob.length);
+                    } else {
 
-                        byte[] buffer = new byte[256];
-                        int len = is.read(buffer);
-                        while (len >= 0) {
-                            baos.write(buffer, 0, len);
-                            len = is.read(buffer);
-                        }
-                    } catch (IOException e) {
-                        Log.e(TAG, "Failed to load part data", e);
-                        c.close();
-                        throw new MmsException(e);
-                    } finally {
-                        if (is != null) {
-                            try {
-                                is.close();
-                            } catch (IOException e) {
-                                Log.e(TAG, "Failed to close stream", e);
-                            } // Ignore
+                        try {
+                            is = mContentResolver.openInputStream(partURI);
+
+                            byte[] buffer = new byte[256];
+                            int len = is.read(buffer);
+                            while (len >= 0) {
+                                baos.write(buffer, 0, len);
+                                len = is.read(buffer);
+                            }
+                        } catch (IOException e) {
+                            Log.e(TAG, "Failed to load part data", e);
+                            c.close();
+                            throw new MmsException(e);
+                        } finally {
+                            if (is != null) {
+                                try {
+                                    is.close();
+                                } catch (IOException e) {
+                                    Log.e(TAG, "Failed to close stream", e);
+                                } // Ignore
+                            }
                         }
                     }
                     part.setData(baos.toByteArray());
@@ -719,29 +734,37 @@
         InputStream is = null;
 
         try {
-            os = mContentResolver.openOutputStream(uri);
             byte[] data = part.getData();
-            if (data == null) {
-                Uri dataUri = part.getDataUri();
-                if ((dataUri == null) || (dataUri == uri)) {
-                    Log.w(TAG, "Can't find data for this part.");
-                    return;
-                }
-                is = mContentResolver.openInputStream(dataUri);
-                
-                if (LOCAL_LOGV) {
-                    Log.v(TAG, "Saving data to: " + uri);
-                }
-
-                byte[] buffer = new byte[256];
-                for (int len = 0; (len = is.read(buffer)) != -1; ) {
-                    os.write(buffer, 0, len);
+            if ("text/plain".equals(contentType) || "application/smil".equals(contentType)) {
+                ContentValues cv = new ContentValues();
+                cv.put(Telephony.Mms.Part.TEXT, new EncodedStringValue(data).getString());
+                if (mContentResolver.update(uri, cv, null, null) != 1) {
+                    throw new MmsException("unable to update " + uri.toString());
                 }
             } else {
-                if (LOCAL_LOGV) {
-                    Log.v(TAG, "Saving data to: " + uri);
+                os = mContentResolver.openOutputStream(uri);
+                if (data == null) {
+                    Uri dataUri = part.getDataUri();
+                    if ((dataUri == null) || (dataUri == uri)) {
+                        Log.w(TAG, "Can't find data for this part.");
+                        return;
+                    }
+                    is = mContentResolver.openInputStream(dataUri);
+
+                    if (LOCAL_LOGV) {
+                        Log.v(TAG, "Saving data to: " + uri);
+                    }
+
+                    byte[] buffer = new byte[256];
+                    for (int len = 0; (len = is.read(buffer)) != -1; ) {
+                        os.write(buffer, 0, len);
+                    }
+                } else {
+                    if (LOCAL_LOGV) {
+                        Log.v(TAG, "Saving data to: " + uri);
+                    }
+                    os.write(data);
                 }
-                os.write(data);
             }
         } catch (FileNotFoundException e) {
             Log.e(TAG, "Failed to open Input/Output stream.", e);
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 251bc84..b5d3b26 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -123,8 +123,7 @@
 	com_android_internal_graphics_NativeUtils.cpp \
 	android_backup_BackupDataInput.cpp \
 	android_backup_BackupDataOutput.cpp \
-	android_backup_FileBackupHelper.cpp \
-	android_backup_RestoreHelperBase.cpp
+	android_backup_FileBackupHelperBase.cpp
 
 LOCAL_C_INCLUDES += \
 	$(JNI_H_INCLUDE) \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 1a1ebb4..f8a4df0 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -155,8 +155,7 @@
 extern int register_android_location_GpsLocationProvider(JNIEnv* env);
 extern int register_android_backup_BackupDataInput(JNIEnv *env);
 extern int register_android_backup_BackupDataOutput(JNIEnv *env);
-extern int register_android_backup_FileBackupHelper(JNIEnv *env);
-extern int register_android_backup_RestoreHelperBase(JNIEnv *env);
+extern int register_android_backup_FileBackupHelperBase(JNIEnv *env);
 
 static AndroidRuntime* gCurRuntime = NULL;
 
@@ -1241,8 +1240,7 @@
     REG_JNI(register_android_location_GpsLocationProvider),
     REG_JNI(register_android_backup_BackupDataInput),
     REG_JNI(register_android_backup_BackupDataOutput),
-    REG_JNI(register_android_backup_FileBackupHelper),
-    REG_JNI(register_android_backup_RestoreHelperBase),
+    REG_JNI(register_android_backup_FileBackupHelperBase),
 };
 
 /*
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 29d8d3c..957b825 100644
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -28,7 +28,7 @@
 static void FromColor_D32(void* dst, const SkColor src[], int width,

                           int, int) {

     SkPMColor* d = (SkPMColor*)dst;

-    

+

     for (int i = 0; i < width; i++) {

         *d++ = SkPreMultiplyColor(*src++);

     }

@@ -37,7 +37,7 @@
 static void FromColor_D565(void* dst, const SkColor src[], int width,

                            int x, int y) {

     uint16_t* d = (uint16_t*)dst;

-    

+

     DITHER_565_SCAN(y);

     for (int stop = x + width; x < stop; x++) {

         SkColor c = *src++;

@@ -49,7 +49,7 @@
 static void FromColor_D4444(void* dst, const SkColor src[], int width,

                             int x, int y) {

     SkPMColor16* d = (SkPMColor16*)dst;

-    

+

     DITHER_4444_SCAN(y);

     for (int stop = x + width; x < stop; x++) {

         SkPMColor c = SkPreMultiplyColor(*src++);

@@ -80,14 +80,14 @@
     SkAutoLockPixels alp(dstBitmap);

     void* dst = dstBitmap.getPixels();

     FromColorProc proc = ChooseFromColorProc(dstBitmap.config());

-    

+

     if (NULL == dst || NULL == proc) {

         return false;

     }

-    

+

     const jint* array = env->GetIntArrayElements(srcColors, NULL);

     const SkColor* src = (const SkColor*)array + srcOffset;

-    

+

     // reset to to actual choice from caller

     dst = dstBitmap.getAddr(x, y);

     // now copy/convert each scanline

@@ -96,7 +96,7 @@
         src += srcStride;

         dst = (char*)dst + dstBitmap.rowBytes();

     }

-    

+

     env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array),

                                  JNI_ABORT);

     return true;

@@ -212,7 +212,7 @@
         doThrowIAE(env, "width and height must be > 0");

         return NULL;

     }

-    

+

     if (NULL != jColors) {

         size_t n = env->GetArrayLength(jColors);

         if (n < SkAbs32(stride) * (size_t)height) {

@@ -222,7 +222,7 @@
     }

 

     SkBitmap bitmap;

-    

+

     bitmap.setConfig(config, width, height);

     if (!GraphicsJNI::setJavaPixelRef(env, &bitmap, NULL)) {

         return NULL;

@@ -232,7 +232,7 @@
         GraphicsJNI::SetPixels(env, jColors, offset, stride,

                                0, 0, width, height, bitmap);

     }

-    

+

     return GraphicsJNI::createBitmap(env, new SkBitmap(bitmap), isMutable,

                                      NULL);

 }

@@ -245,7 +245,7 @@
     if (!src->copyTo(&result, dstConfig, &allocator)) {

         return NULL;

     }

-    

+

     return GraphicsJNI::createBitmap(env, new SkBitmap(result), isMutable,

                                      NULL);

 }

@@ -324,15 +324,15 @@
         SkDebugf("-------- unparcel parcel is NULL\n");

         return NULL;

     }

-    

+

     android::Parcel* p = android::parcelForJavaObject(env, parcel);

-    

+

     const bool              isMutable = p->readInt32() != 0;

     const SkBitmap::Config  config = (SkBitmap::Config)p->readInt32();

     const int               width = p->readInt32();

     const int               height = p->readInt32();

     const int               rowBytes = p->readInt32();

-    

+

     if (SkBitmap::kARGB_8888_Config != config &&

             SkBitmap::kRGB_565_Config != config &&

             SkBitmap::kARGB_4444_Config != config &&

@@ -355,7 +355,7 @@
             ctable = new SkColorTable(src, count);

         }

     }

-    

+

     if (!GraphicsJNI::setJavaPixelRef(env, bitmap, ctable)) {

         ctable->safeUnref();

         delete bitmap;

@@ -368,7 +368,7 @@
     bitmap->lockPixels();

     memcpy(bitmap->getPixels(), p->readInplace(size), size);

     bitmap->unlockPixels();

-    

+

     return GraphicsJNI::createBitmap(env, bitmap, isMutable, NULL);

 }

 

@@ -381,7 +381,7 @@
     }

 

     android::Parcel* p = android::parcelForJavaObject(env, parcel);

-    

+

     p->writeInt32(isMutable);

     p->writeInt32(bitmap->config());

     p->writeInt32(bitmap->width());

@@ -413,7 +413,7 @@
                                    jintArray offsetXY) {

     SkIPoint  offset;

     SkBitmap* dst = new SkBitmap;

-    

+

     src->extractAlpha(dst, paint, &offset);

     if (offsetXY != 0 && env->GetArrayLength(offsetXY) >= 2) {

         int* array = env->GetIntArrayElements(offsetXY, NULL);

@@ -421,7 +421,7 @@
         array[1] = offset.fY;

         env->ReleaseIntArrayElements(offsetXY, array, 0);

     }

-    

+

     return GraphicsJNI::createBitmap(env, dst, true, NULL);

 }

 

@@ -439,7 +439,7 @@
     if (NULL == src) {

         return 0;

     }

-    

+

     SkColor dst[1];

     proc(dst, src, 1, bitmap->getColorTable());

     return dst[0];

@@ -449,7 +449,7 @@
                              jintArray pixelArray, int offset, int stride,

                              int x, int y, int width, int height) {

     SkAutoLockPixels alp(*bitmap);

-    

+

     ToColorProc proc = ChooseToColorProc(*bitmap);

     if (NULL == proc) {

         return;

@@ -498,7 +498,7 @@
                                       const SkBitmap* bitmap, jobject jbuffer) {

     SkAutoLockPixels alp(*bitmap);

     const void* src = bitmap->getPixels();

-    

+

     if (NULL != src) {

         android::AutoBufferPointer abp(env, jbuffer, JNI_TRUE);

 

@@ -511,7 +511,7 @@
                                     const SkBitmap* bitmap, jobject jbuffer) {

     SkAutoLockPixels alp(*bitmap);

     void* dst = bitmap->getPixels();

-    

+

     if (NULL != dst) {

         android::AutoBufferPointer abp(env, jbuffer, JNI_FALSE);

         // the java side has already checked that buffer is large enough

@@ -519,6 +519,11 @@
     }

 }

 

+static void Bitmap_prepareToDraw(JNIEnv* env, jobject, SkBitmap* bitmap) {

+    bitmap->lockPixels();

+    bitmap->unlockPixels();

+}

+

 ///////////////////////////////////////////////////////////////////////////////

 

 #include <android_runtime/AndroidRuntime.h>

@@ -552,7 +557,8 @@
     {   "nativeCopyPixelsToBuffer", "(ILjava/nio/Buffer;)V",

                                             (void*)Bitmap_copyPixelsToBuffer },

     {   "nativeCopyPixelsFromBuffer", "(ILjava/nio/Buffer;)V",

-                                            (void*)Bitmap_copyPixelsFromBuffer }

+                                            (void*)Bitmap_copyPixelsFromBuffer },

+    {   "nativePrepareToDraw",      "(I)V", (void*)Bitmap_prepareToDraw }

 };

 

 #define kClassPathName  "android/graphics/Bitmap"

diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 93d68cb..c61b2ed 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -23,6 +23,7 @@
 #include "SkGLCanvas.h"
 #include "SkGraphics.h"
 #include "SkImageRef_GlobalPool.h"
+#include "SkPorterDuff.h"
 #include "SkShader.h"
 #include "SkTemplates.h"
 
@@ -324,7 +325,7 @@
  
     static void drawColor__II(JNIEnv* env, jobject, SkCanvas* canvas,
                               jint color, SkPorterDuff::Mode mode) {
-        canvas->drawColor(color, mode);
+        canvas->drawColor(color, SkPorterDuff::ToXfermodeMode(mode));
     }
  
     static void drawPaint(JNIEnv* env, jobject, SkCanvas* canvas,
diff --git a/core/jni/android/graphics/ColorFilter.cpp b/core/jni/android/graphics/ColorFilter.cpp
index b6ec4a2..ebfb209 100644
--- a/core/jni/android/graphics/ColorFilter.cpp
+++ b/core/jni/android/graphics/ColorFilter.cpp
@@ -21,6 +21,7 @@
 
 #include "SkColorFilter.h"
 #include "SkColorMatrixFilter.h"
+#include "SkPorterDuff.h"
 
 namespace android {
 
@@ -32,8 +33,9 @@
     }
 
     static SkColorFilter* CreatePorterDuffFilter(JNIEnv* env, jobject,
-                            jint srcColor, SkPorterDuff::Mode porterDuffMode) {
-        return SkColorFilter::CreatePorterDuffFilter(srcColor, porterDuffMode);
+                            jint srcColor, SkPorterDuff::Mode mode) {
+        return SkColorFilter::CreateModeFilter(srcColor,
+                                           SkPorterDuff::ToXfermodeMode(mode));
     }
  
     static SkColorFilter* CreateLightingFilter(JNIEnv* env, jobject,
diff --git a/core/jni/android_backup_BackupDataOutput.cpp b/core/jni/android_backup_BackupDataOutput.cpp
index 6362439..d02590e 100644
--- a/core/jni/android_backup_BackupDataOutput.cpp
+++ b/core/jni/android_backup_BackupDataOutput.cpp
@@ -87,11 +87,26 @@
     return err;
 }
 
+static void
+setKeyPrefix_native(JNIEnv* env, jobject clazz, int w, jstring keyPrefixObj)
+{
+    int err;
+    BackupDataWriter* writer = (BackupDataWriter*)w;
+
+    const char* keyPrefixUTF = env->GetStringUTFChars(keyPrefixObj, NULL);
+    String8 keyPrefix(keyPrefixUTF ? keyPrefixUTF : "");
+
+    writer->SetKeyPrefix(keyPrefix);
+
+    env->ReleaseStringUTFChars(keyPrefixObj, keyPrefixUTF);
+}
+
 static const JNINativeMethod g_methods[] = {
     { "ctor", "(Ljava/io/FileDescriptor;)I", (void*)ctor_native },
     { "dtor", "(I)V", (void*)dtor_native },
     { "writeEntityHeader_native", "(ILjava/lang/String;I)I", (void*)writeEntityHeader_native },
     { "writeEntityData_native", "(I[BI)I", (void*)writeEntityData_native },
+    { "setKeyPrefix_native", "(ILjava/lang/String;)V", (void*)setKeyPrefix_native },
 };
 
 int register_android_backup_BackupDataOutput(JNIEnv* env)
diff --git a/core/jni/android_backup_FileBackupHelper.cpp b/core/jni/android_backup_FileBackupHelperBase.cpp
similarity index 69%
rename from core/jni/android_backup_FileBackupHelper.cpp
rename to core/jni/android_backup_FileBackupHelperBase.cpp
index 418db8a..8225a36 100644
--- a/core/jni/android_backup_FileBackupHelper.cpp
+++ b/core/jni/android_backup_FileBackupHelperBase.cpp
@@ -29,6 +29,18 @@
 static jfieldID s_descriptorField = 0;
 
 static int
+ctor(JNIEnv* env, jobject clazz)
+{
+    return (int)new RestoreHelperBase();
+}
+
+static void
+dtor(JNIEnv* env, jobject clazz, jint ptr)
+{
+    delete (RestoreHelperBase*)ptr;
+}
+
+static int
 performBackup_native(JNIEnv* env, jobject clazz, jobject oldState, int data,
         jobject newState, jobjectArray files, jobjectArray keys)
 {
@@ -66,13 +78,48 @@
     return err;
 }
 
+
+static int
+writeFile_native(JNIEnv* env, jobject clazz, jint ptr, jstring filenameObj, int backupReaderPtr)
+{
+    int err;
+    RestoreHelperBase* restore = (RestoreHelperBase*)ptr;
+    BackupDataReader* reader = (BackupDataReader*)backupReaderPtr;
+    char const* filename;
+
+    filename = env->GetStringUTFChars(filenameObj, NULL);
+
+    err = restore->WriteFile(String8(filename), reader);
+
+    env->ReleaseStringUTFChars(filenameObj, filename);
+
+    return err;
+}
+
+static int
+writeSnapshot_native(JNIEnv* env, jobject clazz, jint ptr, jobject fileDescriptor)
+{
+    int err;
+
+    RestoreHelperBase* restore = (RestoreHelperBase*)ptr;
+    int fd = env->GetIntField(fileDescriptor, s_descriptorField);
+
+    err = restore->WriteSnapshot(fd);
+
+    return err;
+}
+
 static const JNINativeMethod g_methods[] = {
+    { "ctor", "()I", (void*)ctor },
+    { "dtor", "(I)V", (void*)dtor },
     { "performBackup_native",
        "(Ljava/io/FileDescriptor;ILjava/io/FileDescriptor;[Ljava/lang/String;[Ljava/lang/String;)I",
        (void*)performBackup_native },
+    { "writeFile_native", "(ILjava/lang/String;I)I", (void*)writeFile_native },
+    { "writeSnapshot_native", "(ILjava/io/FileDescriptor;)I", (void*)writeSnapshot_native },
 };
 
-int register_android_backup_FileBackupHelper(JNIEnv* env)
+int register_android_backup_FileBackupHelperBase(JNIEnv* env)
 {
     jclass clazz;
 
@@ -82,7 +129,7 @@
     LOG_FATAL_IF(s_descriptorField == NULL,
             "Unable to find descriptor field in java.io.FileDescriptor");
     
-    return AndroidRuntime::registerNativeMethods(env, "android/backup/FileBackupHelper",
+    return AndroidRuntime::registerNativeMethods(env, "android/backup/FileBackupHelperBase",
             g_methods, NELEM(g_methods));
 }
 
diff --git a/core/jni/android_backup_RestoreHelperBase.cpp b/core/jni/android_backup_RestoreHelperBase.cpp
deleted file mode 100644
index 3173420..0000000
--- a/core/jni/android_backup_RestoreHelperBase.cpp
+++ /dev/null
@@ -1,94 +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 "FileBackupHelper_native"
-#include <utils/Log.h>
-
-#include "JNIHelp.h"
-#include <android_runtime/AndroidRuntime.h>
-
-#include <utils/BackupHelpers.h>
-
-namespace android
-{
-
-// java.io.FileDescriptor
-static jfieldID s_descriptorField = 0;
-
-static int
-ctor(JNIEnv* env, jobject clazz)
-{
-    return (int)new RestoreHelperBase();
-}
-
-static void
-dtor(JNIEnv* env, jobject clazz, jint ptr)
-{
-    delete (RestoreHelperBase*)ptr;
-}
-
-static int
-writeFile_native(JNIEnv* env, jobject clazz, jint ptr, jstring filenameObj, int backupReaderPtr)
-{
-    int err;
-    RestoreHelperBase* restore = (RestoreHelperBase*)ptr;
-    BackupDataReader* reader = (BackupDataReader*)backupReaderPtr;
-    char const* filename;
-
-    filename = env->GetStringUTFChars(filenameObj, NULL);
-
-    err = restore->WriteFile(String8(filename), reader);
-
-    env->ReleaseStringUTFChars(filenameObj, filename);
-
-    return err;
-}
-
-static int
-writeSnapshot_native(JNIEnv* env, jobject clazz, jint ptr, jobject fileDescriptor)
-{
-    int err;
-
-    RestoreHelperBase* restore = (RestoreHelperBase*)ptr;
-    int fd = env->GetIntField(fileDescriptor, s_descriptorField);
-
-    err = restore->WriteSnapshot(fd);
-
-    return err;
-}
-
-static const JNINativeMethod g_methods[] = {
-    { "ctor", "()I", (void*)ctor },
-    { "dtor", "(I)V", (void*)dtor },
-    { "writeFile_native", "(ILjava/lang/String;I)I", (void*)writeFile_native },
-    { "writeSnapshot_native", "(ILjava/io/FileDescriptor;)I", (void*)writeSnapshot_native },
-};
-
-int register_android_backup_RestoreHelperBase(JNIEnv* env)
-{
-    jclass clazz;
-
-    clazz = env->FindClass("java/io/FileDescriptor");
-    LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor");
-    s_descriptorField = env->GetFieldID(clazz, "descriptor", "I");
-    LOG_FATAL_IF(s_descriptorField == NULL,
-            "Unable to find descriptor field in java.io.FileDescriptor");
-    
-    return AndroidRuntime::registerNativeMethods(env, "android/backup/RestoreHelperBase",
-            g_methods, NELEM(g_methods));
-}
-
-}
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 217e649..c7cc9b3 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -53,19 +53,33 @@
 static fields_t fields;
 static Mutex sLock;
 
-struct camera_context_t {
+// provides persistent context for calls from native code to Java
+class JNICameraContext: public CameraListener
+{
+public:
+    JNICameraContext(JNIEnv* env, jobject weak_this, jclass clazz, const sp<Camera>& camera);
+    ~JNICameraContext() { release(); }
+    virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2);
+    virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr);
+    sp<Camera> getCamera() { Mutex::Autolock _l(mLock); return mCamera; }
+    void release();
+
+private:
+    void copyAndPost(JNIEnv* env, const sp<IMemory>& dataPtr, int msgType);
+
     jobject     mCameraJObjectWeak;     // weak reference to java object
     jclass      mCameraJClass;          // strong reference to java class
     sp<Camera>  mCamera;                // strong reference to native object 
+    Mutex       mLock;
 };
 
-sp<Camera> get_native_camera(JNIEnv *env, jobject thiz, camera_context_t** pContext)
+sp<Camera> get_native_camera(JNIEnv *env, jobject thiz, JNICameraContext** pContext)
 {
     sp<Camera> camera;
     Mutex::Autolock _l(sLock);
-    camera_context_t* context = reinterpret_cast<camera_context_t*>(env->GetIntField(thiz, fields.context));
+    JNICameraContext* context = reinterpret_cast<JNICameraContext*>(env->GetIntField(thiz, fields.context));
     if (context != NULL) {
-        camera = context->mCamera;
+        camera = context->getCamera();
     }
     LOGV("get_native_camera: context=%p, camera=%p", context, camera.get());
     if (camera == 0) {
@@ -76,30 +90,140 @@
     return camera;
 }
 
-static void err_callback(status_t err, void *cookie)
+JNICameraContext::JNICameraContext(JNIEnv* env, jobject weak_this, jclass clazz, const sp<Camera>& camera)
 {
-    camera_context_t* context = reinterpret_cast<camera_context_t*>(cookie);
-    if ((context == NULL) || (context->mCamera == 0)) return;
+    mCameraJObjectWeak = env->NewGlobalRef(weak_this);
+    mCameraJClass = (jclass)env->NewGlobalRef(clazz);
+    mCamera = camera;
+}
 
-    LOGV("err_callback: context=%p, camera=%p", context, context->mCamera.get());
-
-    int error;
-    switch (err) {
-    case DEAD_OBJECT:
-        error = kCameraErrorMediaServer;
-        break;
-    default:
-        error = kCameraErrorUnknown;
-        break;
-    }
-
+void JNICameraContext::release()
+{
+    LOGV("release");
+    Mutex::Autolock _l(mLock);
     JNIEnv *env = AndroidRuntime::getJNIEnv();
-    if (env == NULL) {
-        LOGE("err_callback on dead VM");
+
+    if (mCameraJObjectWeak != NULL) {
+        env->DeleteGlobalRef(mCameraJObjectWeak);
+        mCameraJObjectWeak = NULL;
+    }
+    if (mCameraJClass != NULL) {
+        env->DeleteGlobalRef(mCameraJClass);
+        mCameraJClass = NULL;
+    }
+    mCamera.clear();
+}
+
+void JNICameraContext::notify(int32_t msgType, int32_t ext1, int32_t ext2)
+{
+    LOGV("notify");
+
+    // VM pointer will be NULL if object is released
+    Mutex::Autolock _l(mLock);
+    if (mCameraJObjectWeak == NULL) {
+        LOGW("callback on dead camera object");
         return;
     }
-    env->CallStaticVoidMethod(context->mCameraJClass, fields.post_event,
-            context->mCameraJObjectWeak, kErrorCallback, error, 0, NULL);
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+
+    // parse message
+    switch (msgType) {
+    case CAMERA_MSG_ERROR:
+        LOGV("errorCallback");
+        int error;
+        switch (ext1) {
+            case DEAD_OBJECT:
+                error = kCameraErrorMediaServer;
+                break;
+            default:
+                error = kCameraErrorUnknown;
+                break;
+        }
+        env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
+                mCameraJObjectWeak, kErrorCallback, error, 0, NULL);
+        break;
+    case CAMERA_MSG_FOCUS:
+        LOGV("autoFocusCallback");
+        env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
+                mCameraJObjectWeak, kAutoFocusCallback, ext1, 0, NULL);
+        break;
+    case CAMERA_MSG_SHUTTER:
+        LOGV("shutterCallback");
+        env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
+                mCameraJObjectWeak, kShutterCallback, 0, 0, NULL);
+        break;
+    default:
+        LOGV("notifyCallback(%d, %d, %d)", msgType, ext1, ext2);
+        break;
+    }
+}
+
+void JNICameraContext::copyAndPost(JNIEnv* env, const sp<IMemory>& dataPtr, int msgType)
+{
+    jbyteArray obj = NULL;
+
+    // allocate Java byte array and copy data
+    if (dataPtr != NULL) {
+        ssize_t offset;
+        size_t size;
+        sp<IMemoryHeap> heap = dataPtr->getMemory(&offset, &size);
+        LOGV("postData: off=%d, size=%d", offset, size);
+        uint8_t *heapBase = (uint8_t*)heap->base();
+
+        if (heapBase != NULL) {
+            uint8_t *data = heapBase + offset;
+            obj = env->NewByteArray(size);
+            if (obj == NULL) {
+                LOGE("Couldn't allocate byte array for JPEG data");
+                env->ExceptionClear();
+            } else {
+                jbyte *bytes = env->GetByteArrayElements(obj, NULL);
+                memcpy(bytes, data, size);
+                env->ReleaseByteArrayElements(obj, bytes, 0);
+
+            }
+        } else {
+            LOGE("image heap is NULL");
+        }
+    }
+
+    // post image data to Java
+    env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
+            mCameraJObjectWeak, msgType, 0, 0, obj);
+    if (obj) {
+        env->DeleteLocalRef(obj);
+    }
+}
+
+void JNICameraContext::postData(int32_t msgType, const sp<IMemory>& dataPtr)
+{
+    // VM pointer will be NULL if object is released
+    Mutex::Autolock _l(mLock);
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+
+    // return data based on callback type
+    switch(msgType) {
+    case CAMERA_MSG_PREVIEW_FRAME:
+        LOGV("previewCallback");
+        copyAndPost(env, dataPtr, kPreviewCallback);
+        break;
+    case CAMERA_MSG_VIDEO_FRAME:
+        LOGV("recordingCallback");
+        break;
+    case CAMERA_MSG_RAW_IMAGE:
+        LOGV("rawCallback");
+        env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
+                mCameraJObjectWeak, kRawCallback, 0, 0, NULL);
+        break;
+    case CAMERA_MSG_COMPRESSED_IMAGE:
+        LOGV("jpegCallback");
+        copyAndPost(env, dataPtr, kJpegCallback);
+        break;
+    default:
+        LOGV("dataCallback(%d, %p)", msgType, dataPtr.get());
+        break;
+    }
+
 }
 
 // connect to camera service
@@ -127,19 +251,12 @@
 
     // We use a weak reference so the Camera object can be garbage collected.
     // The reference is only used as a proxy for callbacks.
-    camera_context_t* context = new camera_context_t;
-    context->mCameraJObjectWeak = env->NewGlobalRef(weak_this);
-    context->mCameraJClass = (jclass)env->NewGlobalRef(clazz);
-    context->mCamera = camera;
+    sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);
+    context->incStrong(thiz);
+    camera->setListener(context);
 
     // save context in opaque field
-    env->SetIntField(thiz, fields.context, (int)context);
-
-    LOGV("native_setup: mCameraJObjectWeak=%x, camera_obj=%x, context=%p",
-            (int)context->mCameraJObjectWeak, (int)thiz, context);
-
-    // set error callback
-    camera->setErrorCallback(err_callback, context);
+    env->SetIntField(thiz, fields.context, (int)context.get());
 }
 
 // disconnect from camera service
@@ -148,11 +265,11 @@
 // finalizer is invoked later.
 static void android_hardware_Camera_release(JNIEnv *env, jobject thiz)
 {
-    camera_context_t* context = NULL;
+    JNICameraContext* context = NULL;
     sp<Camera> camera;
     {
         Mutex::Autolock _l(sLock);
-        context = reinterpret_cast<camera_context_t*>(env->GetIntField(thiz, fields.context));
+        context = reinterpret_cast<JNICameraContext*>(env->GetIntField(thiz, fields.context));
 
         // Make sure we do not attempt to callback on a deleted Java object.
         env->SetIntField(thiz, fields.context, 0);
@@ -160,21 +277,18 @@
 
     // clean up if release has not been called before
     if (context != NULL) {
-        camera = context->mCamera;
-        context->mCamera.clear();
+        camera = context->getCamera();
+        context->release();
         LOGV("native_release: context=%p camera=%p", context, camera.get());
 
         // clear callbacks
         if (camera != NULL) {
-            camera->setPreviewCallback(NULL, NULL, FRAME_CALLBACK_FLAG_NOOP);
-            camera->setErrorCallback(NULL, NULL);
+            camera->setPreviewCallbackFlags(FRAME_CALLBACK_FLAG_NOOP);
             camera->disconnect();
-            env->DeleteGlobalRef(context->mCameraJObjectWeak);
-            env->DeleteGlobalRef(context->mCameraJClass);
         }
 
         // remove context to prevent further Java access
-        delete context;
+        context->decStrong(thiz);
     }
 }
 
@@ -190,48 +304,6 @@
     }
 }
 
-static void preview_callback(const sp<IMemory>& mem, void *cookie)
-{
-    LOGV("preview_callback");
-    JNIEnv *env = AndroidRuntime::getJNIEnv();
-    if (env == NULL) {
-        LOGE("preview_callback on dead VM");
-        return;
-    }
-    camera_context_t* context = reinterpret_cast<camera_context_t*>(cookie);
-    if ((context == NULL) || (context->mCamera == 0)) {
-        LOGW("context or camera is NULL in preview_callback");
-        return;
-    }
-    LOGV("native_release: context=%p camera=%p", context, context->mCamera.get());
-
-    int arg1 = 0, arg2 = 0;
-    jobject obj = NULL;
-
-    ssize_t offset;
-    size_t size;
-    sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
-
-    uint8_t *data = ((uint8_t *)heap->base()) + offset;
-
-    jbyteArray array = env->NewByteArray(size);
-    if (array == NULL) {
-        LOGE("Couldn't allocate byte array for YUV data");
-        env->ExceptionClear();
-        return;
-    }
-
-    jbyte *bytes = env->GetByteArrayElements(array, NULL);
-    memcpy(bytes, data, size);
-    env->ReleaseByteArrayElements(array, bytes, 0);
-
-    obj = array;
-
-    env->CallStaticVoidMethod(context->mCameraJClass, fields.post_event,
-            context->mCameraJObjectWeak, kPreviewCallback, arg1, arg2, obj);
-    env->DeleteLocalRef(array);
-}
-
 static void android_hardware_Camera_startPreview(JNIEnv *env, jobject thiz)
 {
     LOGV("startPreview");
@@ -267,7 +339,7 @@
     // Important: Only install preview_callback if the Java code has called
     // setPreviewCallback() with a non-null value, otherwise we'd pay to memcpy
     // each preview frame for nothing.
-    camera_context_t* context;
+    JNICameraContext* context;
     sp<Camera> camera = get_native_camera(env, thiz, &context);
     if (camera == 0) return;
 
@@ -277,130 +349,32 @@
     } else {
         callback_flag = FRAME_CALLBACK_FLAG_NOOP;
     }
-    camera->setPreviewCallback(installed ? preview_callback : NULL, context, callback_flag);
-}
-
-static void autofocus_callback_impl(bool success, void *cookie)
-{
-    LOGV("autoFocusCallback");
-    camera_context_t* context = reinterpret_cast<camera_context_t*>(cookie);
-
-    JNIEnv *env = AndroidRuntime::getJNIEnv();
-    if (env == NULL) {
-        LOGE("autofocus_callback on dead VM");
-        return;
-    }
-    env->CallStaticVoidMethod(context->mCameraJClass, fields.post_event,
-            context->mCameraJObjectWeak, kAutoFocusCallback, success, 0, NULL);
+    camera->setPreviewCallbackFlags(callback_flag);
 }
 
 static void android_hardware_Camera_autoFocus(JNIEnv *env, jobject thiz)
 {
     LOGV("autoFocus");
-    camera_context_t* context;
+    JNICameraContext* context;
     sp<Camera> c = get_native_camera(env, thiz, &context);
     if (c == 0) return;
 
-    c->setAutoFocusCallback(autofocus_callback_impl, context);
     if (c->autoFocus() != NO_ERROR) {
         jniThrowException(env, "java/lang/RuntimeException", "autoFocus failed");
     }
 }
 
-static void jpeg_callback(const sp<IMemory>& mem, void *cookie)
-{
-    LOGV("jpegCallback");
-    camera_context_t* context = reinterpret_cast<camera_context_t*>(cookie);
-
-    JNIEnv *env = AndroidRuntime::getJNIEnv();
-    if (env == NULL) {
-        LOGE("jpeg`_callback on dead VM");
-        return;
-    }
-    int arg1 = 0, arg2 = 0;
-    jobject obj = NULL;
-
-    if (mem == NULL) {
-        env->CallStaticVoidMethod(context->mCameraJClass, fields.post_event,
-                                  context->mCameraJObjectWeak, kJpegCallback, arg1, arg2, NULL);
-        return;
-    }
-    ssize_t offset;
-    size_t size;
-    sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
-    LOGV("jpeg_callback: mem off=%d, size=%d", offset, size);
-
-    uint8_t *heap_base = (uint8_t *)heap->base();
-    if (heap_base == NULL) {
-        LOGE("YUV heap is NULL");
-        return;
-    }
-
-    uint8_t *data = heap_base + offset;
-
-    jbyteArray array = env->NewByteArray(size);
-    if (array == NULL) {
-        LOGE("Couldn't allocate byte array for JPEG data");
-        env->ExceptionClear();
-        return;
-    }
-
-    jbyte *bytes = env->GetByteArrayElements(array, NULL);
-    memcpy(bytes, data, size);
-    env->ReleaseByteArrayElements(array, bytes, 0);
-
-    obj = array;
-
-    env->CallStaticVoidMethod(context->mCameraJClass, fields.post_event,
-                              context->mCameraJObjectWeak, kJpegCallback, arg1, arg2, obj);
-    env->DeleteLocalRef(array);
-}
-
-static void shutter_callback_impl(void *cookie)
-{
-    LOGV("shutterCallback");
-    camera_context_t* context = reinterpret_cast<camera_context_t*>(cookie);
-
-    JNIEnv *env = AndroidRuntime::getJNIEnv();
-    if (env == NULL) {
-        LOGE("shutter_callback on dead VM");
-        return;
-    }
-    env->CallStaticVoidMethod(context->mCameraJClass, fields.post_event,
-                              context->mCameraJObjectWeak, kShutterCallback, 0, 0, NULL);
-}
-
-static void raw_callback(const sp<IMemory>& mem __attribute__((unused)),
-                         void *cookie)
-{
-    LOGV("rawCallback");
-    camera_context_t* context = reinterpret_cast<camera_context_t*>(cookie);
-
-    JNIEnv *env = AndroidRuntime::getJNIEnv();
-    if (env == NULL) {
-        LOGE("raw_callback on dead VM");
-        return;
-    }
-    env->CallStaticVoidMethod(context->mCameraJClass, fields.post_event,
-                              context->mCameraJObjectWeak, kRawCallback, 0, 0, NULL);
-}
-
 static void android_hardware_Camera_takePicture(JNIEnv *env, jobject thiz)
 {
     LOGV("takePicture");
-    camera_context_t* context;
+    JNICameraContext* context;
     sp<Camera> camera = get_native_camera(env, thiz, &context);
     if (camera == 0) return;
 
-    camera->setShutterCallback(shutter_callback_impl, context);
-    camera->setRawCallback(raw_callback, context);
-    camera->setJpegCallback(jpeg_callback, context);
     if (camera->takePicture() != NO_ERROR) {
         jniThrowException(env, "java/lang/RuntimeException", "takePicture failed");
         return;
     }
-
-    return;
 }
 
 static void android_hardware_Camera_setParameters(JNIEnv *env, jobject thiz, jstring params)
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index c1017d4..0c90769 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -175,6 +175,22 @@
         android:label="@string/permlab_writeDictionary"
         android:description="@string/permdesc_writeDictionary" />
 
+    <!-- Allows an application to read (but not write) the user's
+        browsing history and bookmarks. -->
+    <permission android:name="android.permission.READ_HISTORY_BOOKMARKS"
+        android:permissionGroup="android.permission-group.PERSONAL_INFO"
+        android:label="@string/permlab_readHistoryBookmarks"
+        android:description="@string/permdesc_readHistoryBookmarks"
+        android:protectionLevel="dangerous" />
+
+    <!-- Allows an application to write (but not read) the user's
+        browsing history and bookmarks. -->
+    <permission android:name="android.permission.WRITE_HISTORY_BOOKMARKS"
+        android:permissionGroup="android.permission-group.PERSONAL_INFO"
+        android:label="@string/permlab_writeHistoryBookmarks"
+        android:description="@string/permdesc_writeHistoryBookmarks"
+        android:protectionLevel="dangerous" />
+
     <!-- ======================================= -->
     <!-- Permissions for accessing location info -->
     <!-- ======================================= -->
diff --git a/core/res/res/drawable/search_dropdown_background.9.png b/core/res/res/drawable/search_dropdown_background.9.png
old mode 100755
new mode 100644
index a6923b7..804260a
--- a/core/res/res/drawable/search_dropdown_background.9.png
+++ b/core/res/res/drawable/search_dropdown_background.9.png
Binary files differ
diff --git a/core/res/res/drawable/search_dropdown_background_apps.9.png b/core/res/res/drawable/search_dropdown_background_apps.9.png
deleted file mode 100644
index 804260a..0000000
--- a/core/res/res/drawable/search_dropdown_background_apps.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/layout/search_bar.xml b/core/res/res/layout/search_bar.xml
index 7b7f8a6..13e66aa 100644
--- a/core/res/res/layout/search_bar.xml
+++ b/core/res/res/layout/search_bar.xml
@@ -73,8 +73,10 @@
                 android:paddingRight="6dip"
                 android:drawablePadding="2dip"
                 android:singleLine="true"
+                android:ellipsize="end"
                 android:inputType="text|textAutoComplete"
                 android:dropDownWidth="fill_parent"
+                android:dropDownHeight="fill_parent"
                 android:dropDownAnchor="@id/search_plate"
                 android:dropDownVerticalOffset="-9dip"
                 android:popupBackground="@android:drawable/search_dropdown_background"
diff --git a/core/res/res/values-bg-rBG/donottranslate-cldr.xml b/core/res/res/values-bg-rBG/donottranslate-cldr.xml
index cda072a..b8b50cc 100644
--- a/core/res/res/values-bg-rBG/donottranslate-cldr.xml
+++ b/core/res/res/values-bg-rBG/donottranslate-cldr.xml
@@ -107,19 +107,19 @@
     <string name="abbrev_month_day_year">%d.%m.%Y</string>
     <string name="month_day">%-e %B</string>
     <string name="month">%-B</string>
-    <string name="month_year">%Y %B</string>
+    <string name="month_year">%B %Y</string>
     <string name="abbrev_month_day">%-e %b</string>
-    <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%Y %b</string>
+    <string name="abbrev_month">%b</string>
+    <string name="abbrev_month_year">%b %Y</string>
     <string name="time1_time2">%1$s - %2$s</string>
     <string name="date1_date2">%2$s - %5$s</string>
     <string name="numeric_md1_md2">%3$s.%2$s - %8$s.%7$s</string>
     <string name="numeric_wday1_md1_wday2_md2">%3$s.%2$s, %1$s - %8$s.%7$s, %6$s</string>
     <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%3$s.%2$s.%4$s, %1$s - %8$s.%7$s.%9$s, %6$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s - %10$s %6$s, %9$s-%7$s-%8$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %2$s-%3$s - %10$s %7$s-%8$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %2$s-%3$s - %10$s %6$s, %7$s-%8$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %3$s.%2$s.%4$s, %1$s - %10$s %8$s.%7$s.%9$s, %6$s</string>
+    <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s - %10$s %8$s.%7$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %3$s.%2$s, %1$s - %10$s %8$s.%7$s, %6$s</string>
     <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
     <string name="wday1_date1_time1_wday2_date2_time2">%3$s %2$s, %1$s - %6$s %5$s, %4$s</string>
     <string name="wday1_date1_wday2_date2">%2$s, %1$s - %5$s, %4$s</string>
@@ -135,9 +135,9 @@
     <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %3$s %2$s, %1$s - %10$s %8$s %7$s, %6$s</string>
     <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
     <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s - %10$s %6$s, %9$s %7$s %8$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s - %10$s %6$s, %9$s %7$s %8$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %4$s %2$s %3$s - %6$s, %9$s %7$s %8$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %3$s %2$s %4$s, %1$s - %10$s %8$s %7$s %9$s, %6$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %3$s %2$s %4$s, %1$s - %10$s %8$s %7$s %9$s, %6$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%3$s %2$s %4$s, %1$s - %8$s %7$s %9$s, %6$s</string>
     <string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
     <string name="same_month_wday1_md1_wday2_md2">%3$s %2$s, %1$s - %8$s %7$s, %6$s</string>
     <string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
diff --git a/core/res/res/values-cs-rCZ/donottranslate-cldr.xml b/core/res/res/values-cs-rCZ/donottranslate-cldr.xml
index e933f20..41f5dea 100644
--- a/core/res/res/values-cs-rCZ/donottranslate-cldr.xml
+++ b/core/res/res/values-cs-rCZ/donottranslate-cldr.xml
@@ -117,9 +117,9 @@
     <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s. - %6$s, %8$s.%7$s.</string>
     <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s - %10$s %6$s, %9$s-%7$s-%8$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s - %10$s %6$s, %8$s.%7$s.%9$s</string>
     <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s - %10$s %8$s.%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %2$s-%3$s - %10$s %6$s, %7$s-%8$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s.</string>
     <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
     <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s - %6$s %4$s, %5$s</string>
     <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
diff --git a/core/res/res/values-cs/donottranslate-cldr.xml b/core/res/res/values-cs/donottranslate-cldr.xml
index e933f20..41f5dea 100644
--- a/core/res/res/values-cs/donottranslate-cldr.xml
+++ b/core/res/res/values-cs/donottranslate-cldr.xml
@@ -117,9 +117,9 @@
     <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s. - %6$s, %8$s.%7$s.</string>
     <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s - %10$s %6$s, %9$s-%7$s-%8$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s - %10$s %6$s, %8$s.%7$s.%9$s</string>
     <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s - %10$s %8$s.%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %2$s-%3$s - %10$s %6$s, %7$s-%8$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s.</string>
     <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
     <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s - %6$s %4$s, %5$s</string>
     <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
diff --git a/core/res/res/values-da-rDK/donottranslate-cldr.xml b/core/res/res/values-da-rDK/donottranslate-cldr.xml
index 8cef5b2..2d0db93 100644
--- a/core/res/res/values-da-rDK/donottranslate-cldr.xml
+++ b/core/res/res/values-da-rDK/donottranslate-cldr.xml
@@ -106,7 +106,7 @@
     <string name="time_date">%1$s %3$s</string>
     <string name="abbrev_month_day_year">%d/%m/%Y</string>
     <string name="month_day">%-e. %B</string>
-    <string name="month">%b</string>
+    <string name="month">%B</string>
     <string name="month_year">%B %Y</string>
     <string name="abbrev_month_day">%-e. %b</string>
     <string name="abbrev_month">%b</string>
diff --git a/core/res/res/values-de-rAT/donottranslate-cldr.xml b/core/res/res/values-de-rAT/donottranslate-cldr.xml
index 559e1ee..27624a3 100644
--- a/core/res/res/values-de-rAT/donottranslate-cldr.xml
+++ b/core/res/res/values-de-rAT/donottranslate-cldr.xml
@@ -2,10 +2,43 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="month_long_standalone_january">Jänner</string>
+    <string name="month_long_standalone_february">Februar</string>
+    <string name="month_long_standalone_march">März</string>
+    <string name="month_long_standalone_april">April</string>
+    <string name="month_long_standalone_may">Mai</string>
+    <string name="month_long_standalone_june">Juni</string>
+    <string name="month_long_standalone_july">Juli</string>
+    <string name="month_long_standalone_august">August</string>
+    <string name="month_long_standalone_september">September</string>
+    <string name="month_long_standalone_october">Oktober</string>
+    <string name="month_long_standalone_november">November</string>
+    <string name="month_long_standalone_december">Dezember</string>
 
     <string name="month_long_january">Jänner</string>
+    <string name="month_long_february">Februar</string>
+    <string name="month_long_march">März</string>
+    <string name="month_long_april">April</string>
+    <string name="month_long_may">Mai</string>
+    <string name="month_long_june">Juni</string>
+    <string name="month_long_july">Juli</string>
+    <string name="month_long_august">August</string>
+    <string name="month_long_september">September</string>
+    <string name="month_long_october">Oktober</string>
+    <string name="month_long_november">November</string>
+    <string name="month_long_december">Dezember</string>
 
     <string name="month_medium_january">Jän</string>
+    <string name="month_medium_february">Feb</string>
+    <string name="month_medium_march">Mär</string>
+    <string name="month_medium_april">Apr</string>
+    <string name="month_medium_may">Mai</string>
+    <string name="month_medium_june">Jun</string>
+    <string name="month_medium_july">Jul</string>
+    <string name="month_medium_august">Aug</string>
+    <string name="month_medium_september">Sep</string>
+    <string name="month_medium_october">Okt</string>
+    <string name="month_medium_november">Nov</string>
+    <string name="month_medium_december">Dez</string>
 
     <string name="month_shortest_january">J</string>
     <string name="month_shortest_february">F</string>
@@ -75,7 +108,7 @@
     <string name="month_day">%-e. %B</string>
     <string name="month">%-B</string>
     <string name="month_year">%B %Y</string>
-    <string name="abbrev_month_day">%-e. %b</string>
+    <string name="abbrev_month_day">%d. %b</string>
     <string name="abbrev_month">%-b</string>
     <string name="abbrev_month_year">%b %Y</string>
     <string name="time1_time2">%1$s - %2$s</string>
@@ -84,29 +117,29 @@
     <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s. - %6$s, %8$s.%7$s.</string>
     <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s - %10$s %6$s, %9$s-%7$s-%8$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s - %10$s %6$s, %8$s.%7$s.%9$s</string>
     <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s. - %10$s %8$s.%7$s.</string>
     <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s.</string>
     <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s - %6$s %4$s %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s - %6$s %4$s, %5$s</string>
+    <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
     <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s %3$s</string>
-    <string name="wday_date">%2$s %3$s</string>
+    <string name="time_wday_date">%1$s %2$s, %3$s</string>
+    <string name="wday_date">%2$s, %3$s</string>
     <string name="time_wday">%1$s %2$s</string>
     <string name="same_year_md1_md2">%3$s. %2$s - %8$s. %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s. %2$s - %6$s %8$s. %7$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s</string>
     <string name="same_year_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string>
     <string name="same_month_md1_time1_md2_time2">%5$s %3$s. %2$s - %10$s %8$s. %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s. %2$s - %10$s %6$s %8$s. %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s. %2$s - %10$s %6$s %8$s. %7$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s. %2$s - %10$s %6$s, %8$s. %7$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s. %2$s - %10$s %6$s, %8$s. %7$s</string>
     <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s - %10$s %8$s. %7$s %9$s</string>
     <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s %4$s - %10$s %8$s. %7$s %9$s</string>
     <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s. %2$s %4$s - %10$s %6$s, %8$s. %7$s %9$s</string>
     <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s. %2$s %4$s - %10$s %6$s, %8$s. %7$s %9$s</string>
     <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s %4$s - %6$s, %8$s. %7$s %9$s</string>
     <string name="same_month_md1_md2">%3$s.-%8$s. %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s. %2$s - %6$s %8$s. %7$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s</string>
     <string name="same_year_mdy1_mdy2">%3$s. %2$s - %8$s. %7$s %9$s</string>
     <string name="same_month_mdy1_mdy2">%3$s.-%8$s. %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s. %2$s - %6$s, %8$s. %7$s %9$s</string>
diff --git a/core/res/res/values-de-rCH/donottranslate-cldr.xml b/core/res/res/values-de-rCH/donottranslate-cldr.xml
index 2ca6787..f32095b 100644
--- a/core/res/res/values-de-rCH/donottranslate-cldr.xml
+++ b/core/res/res/values-de-rCH/donottranslate-cldr.xml
@@ -117,7 +117,7 @@
     <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s. - %6$s, %8$s.%7$s.</string>
     <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s - %10$s %6$s, %9$s-%7$s-%8$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s - %10$s %6$s, %8$s.%7$s.%9$s</string>
     <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s. - %10$s %8$s.%7$s.</string>
     <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s.</string>
     <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
diff --git a/core/res/res/values-de-rDE/donottranslate-cldr.xml b/core/res/res/values-de-rDE/donottranslate-cldr.xml
index 2ca6787..f32095b 100644
--- a/core/res/res/values-de-rDE/donottranslate-cldr.xml
+++ b/core/res/res/values-de-rDE/donottranslate-cldr.xml
@@ -117,7 +117,7 @@
     <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s. - %6$s, %8$s.%7$s.</string>
     <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s - %10$s %6$s, %9$s-%7$s-%8$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s - %10$s %6$s, %8$s.%7$s.%9$s</string>
     <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s. - %10$s %8$s.%7$s.</string>
     <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s.</string>
     <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
diff --git a/core/res/res/values-de-rLI/donottranslate-cldr.xml b/core/res/res/values-de-rLI/donottranslate-cldr.xml
index 2ca6787..f32095b 100644
--- a/core/res/res/values-de-rLI/donottranslate-cldr.xml
+++ b/core/res/res/values-de-rLI/donottranslate-cldr.xml
@@ -117,7 +117,7 @@
     <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s. - %6$s, %8$s.%7$s.</string>
     <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s - %10$s %6$s, %9$s-%7$s-%8$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s - %10$s %6$s, %8$s.%7$s.%9$s</string>
     <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s. - %10$s %8$s.%7$s.</string>
     <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s.</string>
     <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
diff --git a/core/res/res/values-de/donottranslate-cldr.xml b/core/res/res/values-de/donottranslate-cldr.xml
index 2ca6787..f32095b 100644
--- a/core/res/res/values-de/donottranslate-cldr.xml
+++ b/core/res/res/values-de/donottranslate-cldr.xml
@@ -117,7 +117,7 @@
     <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s. - %6$s, %8$s.%7$s.</string>
     <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s - %10$s %6$s, %9$s-%7$s-%8$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s - %10$s %6$s, %8$s.%7$s.%9$s</string>
     <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s. - %10$s %8$s.%7$s.</string>
     <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s. - %10$s %6$s, %8$s.%7$s.</string>
     <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
diff --git a/core/res/res/values-en-rAU/donottranslate-cldr.xml b/core/res/res/values-en-rAU/donottranslate-cldr.xml
index 5d1a8f6..9811b68 100644
--- a/core/res/res/values-en-rAU/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rAU/donottranslate-cldr.xml
@@ -108,8 +108,8 @@
     <string name="month_day">%-e %B</string>
     <string name="month">%-B</string>
     <string name="month_year">%B %Y</string>
-    <string name="abbrev_month_day">%b %-e</string>
-    <string name="abbrev_month">%-b</string>
+    <string name="abbrev_month_day">%-e %b</string>
+    <string name="abbrev_month">%b</string>
     <string name="abbrev_month_year">%b %Y</string>
     <string name="time1_time2">%1$s - %2$s</string>
     <string name="date1_date2">%2$s - %5$s</string>
@@ -117,9 +117,9 @@
     <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s/%2$s - %6$s, %8$s/%7$s</string>
     <string name="numeric_mdy1_mdy2">%3$s/%2$s/%4$s - %8$s/%7$s/%9$s</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s/%2$s/%4$s - %6$s, %8$s/%7$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s/%3$s/%4$s, %5$s - %6$s, %7$s/%8$s/%9$s, %10$s</string>
-    <string name="numeric_md1_time1_md2_time2">%2$s/%3$s, %5$s - %7$s/%8$s, %10$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s/%3$s, %5$s - %6$s, %7$s/%8$s, %10$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s/%2$s/%4$s, %5$s - %6$s, %8$s/%7$s/%9$s, %10$s</string>
+    <string name="numeric_md1_time1_md2_time2">%3$s/%2$s, %5$s - %8$s/%7$s, %10$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s/%2$s, %5$s - %6$s, %8$s/%7$s, %10$s</string>
     <string name="numeric_mdy1_time1_mdy2_time2">%3$s/%2$s/%4$s, %5$s - %8$s/%7$s/%9$s, %10$s</string>
     <string name="wday1_date1_time1_wday2_date2_time2">%1$s, %2$s, %3$s - %4$s, %5$s, %6$s</string>
     <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
@@ -128,18 +128,18 @@
     <string name="wday_date">%2$s, %3$s</string>
     <string name="time_wday">%1$s, %2$s</string>
     <string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s, %2$s %3$s - %6$s, %7$s %8$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s %2$s - %6$s, %8$s %7$s</string>
     <string name="same_year_md1_time1_md2_time2">%3$s %2$s, %5$s - %8$s %7$s, %10$s</string>
     <string name="same_month_md1_time1_md2_time2">%3$s %2$s, %5$s - %8$s %7$s, %10$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s %3$s, %5$s - %6$s, %7$s %8$s, %10$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s %3$s, %5$s - %6$s, %7$s %8$s, %10$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s %2$s, %5$s - %6$s, %8$s %7$s, %10$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s %2$s, %5$s - %6$s, %8$s %7$s, %10$s</string>
     <string name="same_year_mdy1_time1_mdy2_time2">%3$s %2$s %4$s, %5$s - %8$s %7$s %9$s, %10$s</string>
     <string name="same_month_mdy1_time1_mdy2_time2">%3$s %2$s %4$s, %5$s - %8$s %7$s %9$s, %10$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s %3$s, %4$s, %5$s - %6$s, %7$s %8$s, %9$s, %10$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s %3$s, %4$s, %5$s - %6$s, %7$s %8$s, %9$s, %10$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %2$s %3$s, %4$s - %6$s, %7$s %8$s, %9$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s %2$s %4$s, %5$s - %6$s, %8$s %7$s %9$s, %10$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s %2$s %4$s, %5$s - %6$s, %8$s %7$s %9$s, %10$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s %4$s - %6$s, %8$s %7$s %9$s</string>
     <string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s, %2$s %3$s - %6$s, %7$s %8$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s, %3$s %2$s - %6$s, %8$s %7$s</string>
     <string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
     <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s - %6$s, %8$s %7$s %9$s</string>
diff --git a/core/res/res/values-en-rCA/donottranslate-cldr.xml b/core/res/res/values-en-rCA/donottranslate-cldr.xml
index 5d7300e..1e250c7 100644
--- a/core/res/res/values-en-rCA/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rCA/donottranslate-cldr.xml
@@ -109,7 +109,7 @@
     <string name="month">%-B</string>
     <string name="month_year">%B %Y</string>
     <string name="abbrev_month_day">%b %-e</string>
-    <string name="abbrev_month">%-b</string>
+    <string name="abbrev_month">%b</string>
     <string name="abbrev_month_year">%b %Y</string>
     <string name="time1_time2">%1$s - %2$s</string>
     <string name="date1_date2">%2$s - %5$s</string>
@@ -117,9 +117,9 @@
     <string name="numeric_wday1_md1_wday2_md2">%1$s, %2$s-%3$s - %6$s, %7$s-%8$s</string>
     <string name="numeric_mdy1_mdy2">%4$s-%2$s-%3$s - %9$s-%7$s-%8$s</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %4$s-%2$s-%3$s - %6$s, %9$s-%7$s-%8$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s/%3$s/%4$s, %5$s - %6$s, %7$s/%8$s/%9$s, %10$s</string>
-    <string name="numeric_md1_time1_md2_time2">%2$s/%3$s, %5$s - %7$s/%8$s, %10$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s/%3$s, %5$s - %6$s, %7$s/%8$s, %10$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %4$s-%2$s-%3$s, %5$s - %6$s, %9$s-%7$s-%8$s, %10$s</string>
+    <string name="numeric_md1_time1_md2_time2">%2$s-%3$s, %5$s - %7$s-%8$s, %10$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s-%3$s, %5$s - %6$s, %7$s-%8$s, %10$s</string>
     <string name="numeric_mdy1_time1_mdy2_time2">%4$s-%2$s-%3$s, %5$s - %9$s-%7$s-%8$s, %10$s</string>
     <string name="wday1_date1_time1_wday2_date2_time2">%1$s, %2$s, %3$s - %4$s, %5$s, %6$s</string>
     <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
diff --git a/core/res/res/values-en-rGB/donottranslate-cldr.xml b/core/res/res/values-en-rGB/donottranslate-cldr.xml
index b115c6e..0e3e035 100644
--- a/core/res/res/values-en-rGB/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rGB/donottranslate-cldr.xml
@@ -108,8 +108,8 @@
     <string name="month_day">%-e %B</string>
     <string name="month">%-B</string>
     <string name="month_year">%B %Y</string>
-    <string name="abbrev_month_day">%b %-e</string>
-    <string name="abbrev_month">%-b</string>
+    <string name="abbrev_month_day">%-e %b</string>
+    <string name="abbrev_month">%b</string>
     <string name="abbrev_month_year">%b %Y</string>
     <string name="time1_time2">%1$s - %2$s</string>
     <string name="date1_date2">%2$s - %5$s</string>
@@ -121,11 +121,11 @@
     <string name="numeric_md1_time1_md2_time2">%3$s/%2$s, %5$s - %8$s/%7$s, %10$s</string>
     <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s/%2$s, %5$s - %6$s, %8$s/%7$s, %10$s</string>
     <string name="numeric_mdy1_time1_mdy2_time2">%3$s/%2$s/%4$s, %5$s - %8$s/%7$s/%9$s, %10$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%1$s, %2$s, %3$s - %4$s, %5$s, %6$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%1$s %2$s, %3$s - %4$s %5$s, %6$s</string>
+    <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string>
     <string name="date1_time1_date2_time2">%2$s, %3$s - %5$s, %6$s</string>
-    <string name="time_wday_date">%1$s, %2$s, %3$s</string>
-    <string name="wday_date">%2$s, %3$s</string>
+    <string name="time_wday_date">%1$s, %2$s %3$s</string>
+    <string name="wday_date">%2$s %3$s</string>
     <string name="time_wday">%1$s, %2$s</string>
     <string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string>
     <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
@@ -135,9 +135,9 @@
     <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s %3$s %2$s, %5$s - %6$s %8$s %7$s, %10$s</string>
     <string name="same_year_mdy1_time1_mdy2_time2">%3$s %2$s %4$s, %5$s - %8$s %7$s %9$s, %10$s</string>
     <string name="same_month_mdy1_time1_mdy2_time2">%3$s %2$s %4$s, %5$s - %8$s %7$s %9$s, %10$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s %3$s, %4$s, %5$s - %6$s, %7$s %8$s, %9$s, %10$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s %3$s, %4$s, %5$s - %6$s, %7$s %8$s, %9$s, %10$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %2$s %3$s, %4$s - %6$s, %7$s %8$s, %9$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s %2$s %4$s, %5$s - %6$s, %8$s %7$s %9$s, %10$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s %2$s %4$s, %5$s - %6$s, %8$s %7$s %9$s, %10$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s %4$s - %6$s, %8$s %7$s %9$s</string>
     <string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
     <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
     <string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
diff --git a/core/res/res/values-en-rIE/donottranslate-cldr.xml b/core/res/res/values-en-rIE/donottranslate-cldr.xml
index 15fc8e8..2e59dcf 100644
--- a/core/res/res/values-en-rIE/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rIE/donottranslate-cldr.xml
@@ -108,8 +108,8 @@
     <string name="month_day">%-e %B</string>
     <string name="month">%-B</string>
     <string name="month_year">%B %Y</string>
-    <string name="abbrev_month_day">%b %-e</string>
-    <string name="abbrev_month">%-b</string>
+    <string name="abbrev_month_day">%-e %b</string>
+    <string name="abbrev_month">%b</string>
     <string name="abbrev_month_year">%b %Y</string>
     <string name="time1_time2">%1$s - %2$s</string>
     <string name="date1_date2">%2$s - %5$s</string>
@@ -121,25 +121,25 @@
     <string name="numeric_md1_time1_md2_time2">%3$s/%2$s, %5$s - %8$s/%7$s, %10$s</string>
     <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s/%2$s, %5$s - %6$s, %8$s/%7$s, %10$s</string>
     <string name="numeric_mdy1_time1_mdy2_time2">%3$s/%2$s/%4$s, %5$s - %8$s/%7$s/%9$s, %10$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%1$s, %2$s, %3$s - %4$s, %5$s, %6$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%1$s %2$s, %3$s - %4$s %5$s, %6$s</string>
+    <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string>
     <string name="date1_time1_date2_time2">%2$s, %3$s - %5$s, %6$s</string>
-    <string name="time_wday_date">%1$s, %2$s, %3$s</string>
-    <string name="wday_date">%2$s, %3$s</string>
+    <string name="time_wday_date">%1$s, %2$s %3$s</string>
+    <string name="wday_date">%2$s %3$s</string>
     <string name="time_wday">%1$s, %2$s</string>
     <string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s, %2$s %3$s - %6$s, %7$s %8$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
     <string name="same_year_md1_time1_md2_time2">%3$s %2$s, %5$s - %8$s %7$s, %10$s</string>
     <string name="same_month_md1_time1_md2_time2">%3$s %2$s, %5$s - %8$s %7$s, %10$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s %3$s, %5$s - %6$s, %7$s %8$s, %10$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s %3$s, %5$s - %6$s, %7$s %8$s, %10$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%1$s %3$s %2$s, %5$s - %6$s %8$s %7$s, %10$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s %3$s %2$s, %5$s - %6$s %8$s %7$s, %10$s</string>
     <string name="same_year_mdy1_time1_mdy2_time2">%3$s %2$s %4$s, %5$s - %8$s %7$s %9$s, %10$s</string>
     <string name="same_month_mdy1_time1_mdy2_time2">%3$s %2$s %4$s, %5$s - %8$s %7$s %9$s, %10$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s %3$s, %4$s, %5$s - %6$s, %7$s %8$s, %9$s, %10$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s %3$s, %4$s, %5$s - %6$s, %7$s %8$s, %9$s, %10$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %2$s %3$s, %4$s - %6$s, %7$s %8$s, %9$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s %3$s %2$s %4$s, %5$s - %6$s %8$s %7$s %9$s, %10$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s %3$s %2$s %4$s, %5$s - %6$s %8$s %7$s %9$s, %10$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s %4$s - %6$s %8$s %7$s %9$s</string>
     <string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s, %2$s %3$s - %6$s, %7$s %8$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
     <string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
     <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s - %6$s %8$s %7$s %9$s</string>
diff --git a/core/res/res/values-en-rIN/donottranslate-cldr.xml b/core/res/res/values-en-rIN/donottranslate-cldr.xml
index 2507ee8..e39a59a 100644
--- a/core/res/res/values-en-rIN/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rIN/donottranslate-cldr.xml
@@ -108,8 +108,8 @@
     <string name="month_day">%-e %B</string>
     <string name="month">%-B</string>
     <string name="month_year">%B %Y</string>
-    <string name="abbrev_month_day">%b %-e</string>
-    <string name="abbrev_month">%-b</string>
+    <string name="abbrev_month_day">%-e %b</string>
+    <string name="abbrev_month">%b</string>
     <string name="abbrev_month_year">%b %Y</string>
     <string name="time1_time2">%1$s - %2$s</string>
     <string name="date1_date2">%2$s - %5$s</string>
@@ -117,29 +117,29 @@
     <string name="numeric_wday1_md1_wday2_md2">%1$s %3$s/%2$s - %6$s %8$s/%7$s</string>
     <string name="numeric_mdy1_mdy2">%3$s/%2$s/%4$s - %8$s/%7$s/%9$s</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %3$s/%2$s/%4$s - %6$s %8$s/%7$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s/%3$s/%4$s, %5$s - %6$s, %7$s/%8$s/%9$s, %10$s</string>
-    <string name="numeric_md1_time1_md2_time2">%2$s/%3$s, %5$s - %7$s/%8$s, %10$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s/%3$s, %5$s - %6$s, %7$s/%8$s, %10$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%1$s %3$s/%2$s/%4$s, %5$s - %6$s %8$s/%7$s/%9$s, %10$s</string>
+    <string name="numeric_md1_time1_md2_time2">%3$s/%2$s, %5$s - %8$s/%7$s, %10$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s %3$s/%2$s, %5$s - %6$s %8$s/%7$s, %10$s</string>
     <string name="numeric_mdy1_time1_mdy2_time2">%3$s/%2$s/%4$s, %5$s - %8$s/%7$s/%9$s, %10$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%1$s, %2$s, %3$s - %4$s, %5$s, %6$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%1$s %2$s, %3$s - %4$s %5$s, %6$s</string>
+    <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string>
     <string name="date1_time1_date2_time2">%2$s, %3$s - %5$s, %6$s</string>
-    <string name="time_wday_date">%1$s, %2$s, %3$s</string>
-    <string name="wday_date">%2$s, %3$s</string>
+    <string name="time_wday_date">%1$s, %2$s %3$s</string>
+    <string name="wday_date">%2$s %3$s</string>
     <string name="time_wday">%1$s, %2$s</string>
     <string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s, %2$s %3$s - %6$s, %7$s %8$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
     <string name="same_year_md1_time1_md2_time2">%3$s %2$s, %5$s - %8$s %7$s, %10$s</string>
     <string name="same_month_md1_time1_md2_time2">%3$s %2$s, %5$s - %8$s %7$s, %10$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s %3$s, %5$s - %6$s, %7$s %8$s, %10$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s %3$s, %5$s - %6$s, %7$s %8$s, %10$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%1$s %3$s %2$s, %5$s - %6$s %8$s %7$s, %10$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s %3$s %2$s, %5$s - %6$s %8$s %7$s, %10$s</string>
     <string name="same_year_mdy1_time1_mdy2_time2">%3$s %2$s %4$s, %5$s - %8$s %7$s %9$s, %10$s</string>
     <string name="same_month_mdy1_time1_mdy2_time2">%3$s %2$s %4$s, %5$s - %8$s %7$s %9$s, %10$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s %3$s, %4$s, %5$s - %6$s, %7$s %8$s, %9$s, %10$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s %3$s, %4$s, %5$s - %6$s, %7$s %8$s, %9$s, %10$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %2$s %3$s, %4$s - %6$s, %7$s %8$s, %9$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s %3$s %2$s %4$s, %5$s - %6$s %8$s %7$s %9$s, %10$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s %3$s %2$s %4$s, %5$s - %6$s %8$s %7$s %9$s, %10$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s %4$s - %6$s %8$s %7$s %9$s</string>
     <string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s, %2$s %3$s - %6$s, %7$s %8$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
     <string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
     <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s - %6$s %8$s %7$s %9$s</string>
diff --git a/core/res/res/values-en-rNZ/donottranslate-cldr.xml b/core/res/res/values-en-rNZ/donottranslate-cldr.xml
index 07d4fe8..3a8b50b 100644
--- a/core/res/res/values-en-rNZ/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rNZ/donottranslate-cldr.xml
@@ -108,8 +108,8 @@
     <string name="month_day">%-e %B</string>
     <string name="month">%-B</string>
     <string name="month_year">%B %Y</string>
-    <string name="abbrev_month_day">%b %-e</string>
-    <string name="abbrev_month">%-b</string>
+    <string name="abbrev_month_day">%-e %b</string>
+    <string name="abbrev_month">%b</string>
     <string name="abbrev_month_year">%b %Y</string>
     <string name="time1_time2">%1$s - %2$s</string>
     <string name="date1_date2">%2$s - %5$s</string>
@@ -117,9 +117,9 @@
     <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s/%2$s - %6$s, %8$s/%7$s</string>
     <string name="numeric_mdy1_mdy2">%3$s/%2$s/%4$s - %8$s/%7$s/%9$s</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s/%2$s/%4$s - %6$s, %8$s/%7$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s/%3$s/%4$s, %5$s - %6$s, %7$s/%8$s/%9$s, %10$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s/%2$s/%4$s, %5$s - %6$s, %8$s/%7$s/%9$s, %10$s</string>
     <string name="numeric_md1_time1_md2_time2">%3$s/%2$s, %5$s - %8$s/%7$s, %10$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s/%3$s, %5$s - %6$s, %7$s/%8$s, %10$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s/%2$s, %5$s - %6$s, %8$s/%7$s, %10$s</string>
     <string name="numeric_mdy1_time1_mdy2_time2">%3$s/%2$s/%4$s, %5$s - %8$s/%7$s/%9$s, %10$s</string>
     <string name="wday1_date1_time1_wday2_date2_time2">%1$s, %2$s, %3$s - %4$s, %5$s, %6$s</string>
     <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
@@ -128,18 +128,18 @@
     <string name="wday_date">%2$s, %3$s</string>
     <string name="time_wday">%1$s, %2$s</string>
     <string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s, %2$s %3$s - %6$s, %7$s %8$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s %2$s - %6$s, %8$s %7$s</string>
     <string name="same_year_md1_time1_md2_time2">%3$s %2$s, %5$s - %8$s %7$s, %10$s</string>
     <string name="same_month_md1_time1_md2_time2">%3$s %2$s, %5$s - %8$s %7$s, %10$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s %3$s, %5$s - %6$s, %7$s %8$s, %10$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s %3$s, %5$s - %6$s, %7$s %8$s, %10$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s %2$s, %5$s - %6$s, %8$s %7$s, %10$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s, %3$s %2$s, %5$s - %6$s, %8$s %7$s, %10$s</string>
     <string name="same_year_mdy1_time1_mdy2_time2">%3$s %2$s %4$s, %5$s - %8$s %7$s %9$s, %10$s</string>
     <string name="same_month_mdy1_time1_mdy2_time2">%3$s %2$s %4$s, %5$s - %8$s %7$s %9$s, %10$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s %3$s, %4$s, %5$s - %6$s, %7$s %8$s, %9$s, %10$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s %3$s, %4$s, %5$s - %6$s, %7$s %8$s, %9$s, %10$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %2$s %3$s, %4$s - %6$s, %7$s %8$s, %9$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s %2$s %4$s, %5$s - %6$s, %8$s %7$s %9$s, %10$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %3$s %2$s %4$s, %5$s - %6$s, %8$s %7$s %9$s, %10$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s %4$s - %6$s, %8$s %7$s %9$s</string>
     <string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s, %2$s %3$s - %6$s, %7$s %8$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s, %3$s %2$s - %6$s, %8$s %7$s</string>
     <string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
     <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s - %6$s, %8$s %7$s %9$s</string>
diff --git a/core/res/res/values-en-rZA/donottranslate-cldr.xml b/core/res/res/values-en-rZA/donottranslate-cldr.xml
index 9e8681b..2e2d608 100644
--- a/core/res/res/values-en-rZA/donottranslate-cldr.xml
+++ b/core/res/res/values-en-rZA/donottranslate-cldr.xml
@@ -108,8 +108,8 @@
     <string name="month_day">%B %-e</string>
     <string name="month">%-B</string>
     <string name="month_year">%B %Y</string>
-    <string name="abbrev_month_day">%b %-e</string>
-    <string name="abbrev_month">%-b</string>
+    <string name="abbrev_month_day">%d %b</string>
+    <string name="abbrev_month">%b</string>
     <string name="abbrev_month_year">%b %Y</string>
     <string name="time1_time2">%1$s - %2$s</string>
     <string name="date1_date2">%2$s - %5$s</string>
@@ -117,29 +117,29 @@
     <string name="numeric_wday1_md1_wday2_md2">%1$s %2$s/%3$s - %6$s %7$s/%8$s</string>
     <string name="numeric_mdy1_mdy2">%4$s/%2$s/%3$s - %9$s/%7$s/%8$s</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %4$s/%2$s/%3$s - %6$s %9$s/%7$s/%8$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s/%3$s/%4$s, %5$s - %6$s, %7$s/%8$s/%9$s, %10$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%1$s %4$s/%2$s/%3$s, %5$s - %6$s %9$s/%7$s/%8$s, %10$s</string>
     <string name="numeric_md1_time1_md2_time2">%2$s/%3$s, %5$s - %7$s/%8$s, %10$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s/%3$s, %5$s - %6$s, %7$s/%8$s, %10$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%1$s %2$s/%3$s, %5$s - %6$s %7$s/%8$s, %10$s</string>
     <string name="numeric_mdy1_time1_mdy2_time2">%4$s/%2$s/%3$s, %5$s - %9$s/%7$s/%8$s, %10$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%1$s, %2$s, %3$s - %4$s, %5$s, %6$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%1$s %2$s, %3$s - %4$s %5$s, %6$s</string>
+    <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string>
     <string name="date1_time1_date2_time2">%2$s, %3$s - %5$s, %6$s</string>
-    <string name="time_wday_date">%1$s, %2$s, %3$s</string>
-    <string name="wday_date">%2$s, %3$s</string>
+    <string name="time_wday_date">%1$s, %2$s %3$s</string>
+    <string name="wday_date">%2$s %3$s</string>
     <string name="time_wday">%1$s, %2$s</string>
     <string name="same_year_md1_md2">%2$s %3$s - %7$s %8$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s, %2$s %3$s - %6$s, %7$s %8$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
     <string name="same_year_md1_time1_md2_time2">%2$s %3$s, %5$s - %7$s %8$s, %10$s</string>
     <string name="same_month_md1_time1_md2_time2">%2$s %3$s, %5$s - %7$s %8$s, %10$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s %3$s, %5$s - %6$s, %7$s %8$s, %10$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s, %2$s %3$s, %5$s - %6$s, %7$s %8$s, %10$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%1$s %3$s %2$s, %5$s - %6$s %8$s %7$s, %10$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%1$s %3$s %2$s, %5$s - %6$s %8$s %7$s, %10$s</string>
     <string name="same_year_mdy1_time1_mdy2_time2">%3$s %2$s %4$s, %5$s - %8$s %7$s %9$s, %10$s</string>
     <string name="same_month_mdy1_time1_mdy2_time2">%3$s %2$s %4$s, %5$s - %8$s %7$s %9$s, %10$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s %3$s, %4$s, %5$s - %6$s, %7$s %8$s, %9$s, %10$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s, %2$s %3$s, %4$s, %5$s - %6$s, %7$s %8$s, %9$s, %10$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %2$s %3$s, %4$s - %6$s, %7$s %8$s, %9$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%1$s %3$s %2$s %4$s, %5$s - %6$s %8$s %7$s %9$s, %10$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%1$s %3$s %2$s %4$s, %5$s - %6$s %8$s %7$s %9$s, %10$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s %4$s - %6$s %8$s %7$s %9$s</string>
     <string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s, %2$s %3$s - %6$s, %7$s %8$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
     <string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
     <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s - %6$s %8$s %7$s %9$s</string>
diff --git a/core/res/res/values-es-rUS/donottranslate-cldr.xml b/core/res/res/values-es-rUS/donottranslate-cldr.xml
index 24923c3..d6d8954 100644
--- a/core/res/res/values-es-rUS/donottranslate-cldr.xml
+++ b/core/res/res/values-es-rUS/donottranslate-cldr.xml
@@ -108,18 +108,18 @@
     <string name="month_day">%-e de %B</string>
     <string name="month">%-B</string>
     <string name="month_year">%B de %Y</string>
-    <string name="abbrev_month_day">%-e %b</string>
-    <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%b %Y</string>
+    <string name="abbrev_month_day">%-e de %b</string>
+    <string name="abbrev_month">%b</string>
+    <string name="abbrev_month_year">%b de %Y</string>
     <string name="time1_time2">%1$s a el %2$s</string>
     <string name="date1_date2">%2$s a el %5$s</string>
     <string name="numeric_md1_md2">%2$s/%3$s - %7$s/%8$s</string>
     <string name="numeric_wday1_md1_wday2_md2">%1$s %2$s/%3$s - %6$s %7$s/%8$s</string>
     <string name="numeric_mdy1_mdy2">%2$s/%3$s/%4$s - %7$s/%8$s/%9$s</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %2$s/%3$s/%4$s - %6$s %7$s/%8$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s/%2$s/%4$s a el %10$s %6$s %8$s/%7$s/%9$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %2$s/%3$s/%4$s a el %10$s %6$s %7$s/%8$s/%9$s</string>
     <string name="numeric_md1_time1_md2_time2">%5$s %2$s/%3$s a el %10$s %7$s/%8$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s-%2$s a el %10$s %6$s, %8$s-%7$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s/%3$s a el %10$s %6$s %7$s/%8$s</string>
     <string name="numeric_mdy1_time1_mdy2_time2">%5$s %2$s/%3$s/%4$s a el %10$s %7$s/%8$s/%9$s</string>
     <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s a el %6$s %4$s %5$s</string>
     <string name="wday1_date1_wday2_date2">%1$s %2$s a el %4$s %5$s</string>
@@ -128,18 +128,18 @@
     <string name="wday_date">%2$s %3$s</string>
     <string name="time_wday">%1$s %2$s</string>
     <string name="same_year_md1_md2">%3$s de %2$s a el %8$s de %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s a el %6$s %8$s %7$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s de %2$s a el %6$s %8$s de %7$s</string>
     <string name="same_year_md1_time1_md2_time2">%5$s %3$s de %2$s a el %10$s %8$s de %7$s</string>
     <string name="same_month_md1_time1_md2_time2">%5$s %3$s de %2$s a el %10$s %8$s de %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s a el %10$s %6$s %8$s %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s a el %10$s %6$s %8$s %7$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s de %2$s a el %10$s %6$s %8$s de %7$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s de %2$s a el %10$s %6$s %8$s de %7$s</string>
     <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s de %2$s de %4$s a el %10$s %8$s de %7$s de %9$s</string>
     <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s de %2$s de %4$s a el %10$s %8$s de %7$s de %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s a el %10$s %6$s, %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s a el %10$s %6$s, %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s %4$s a el %6$s, %8$s %7$s %9$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s de %2$s de %4$s a el %10$s %6$s %8$s de %7$s de %9$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s de %2$s de %4$s a el %10$s %6$s %8$s de %7$s de %9$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s de %2$s de %4$s a el %6$s %8$s de %7$s de %9$s</string>
     <string name="same_month_md1_md2">%3$s-%8$s de %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s a el %6$s %8$s %7$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s de %2$s a el %6$s %8$s de %7$s</string>
     <string name="same_year_mdy1_mdy2">%3$s de %2$s al %8$s de %7$s de %9$s</string>
     <string name="same_month_mdy1_mdy2">%3$s-%8$s de %2$s de %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s %3$s de %2$s al %6$s %8$s de %7$s de %9$s</string>
diff --git a/core/res/res/values-fi-rFI/donottranslate-cldr.xml b/core/res/res/values-fi-rFI/donottranslate-cldr.xml
index dd12e57..df3866e 100644
--- a/core/res/res/values-fi-rFI/donottranslate-cldr.xml
+++ b/core/res/res/values-fi-rFI/donottranslate-cldr.xml
@@ -106,7 +106,7 @@
     <string name="time_date">%1$s %3$s</string>
     <string name="abbrev_month_day_year">%-e.%-m.%Y</string>
     <string name="month_day">%-e. %B</string>
-    <string name="month">%-B</string>
+    <string name="month">%-b</string>
     <string name="month_year">%-B %Y</string>
     <string name="abbrev_month_day">%-e. %b</string>
     <string name="abbrev_month">%-b</string>
diff --git a/core/res/res/values-fr-rBE/donottranslate-cldr.xml b/core/res/res/values-fr-rBE/donottranslate-cldr.xml
index ea4ecf2..e190837 100644
--- a/core/res/res/values-fr-rBE/donottranslate-cldr.xml
+++ b/core/res/res/values-fr-rBE/donottranslate-cldr.xml
@@ -109,7 +109,7 @@
     <string name="month">%-B</string>
     <string name="month_year">%B %Y</string>
     <string name="abbrev_month_day">%-e %b</string>
-    <string name="abbrev_month">%-b</string>
+    <string name="abbrev_month">%b</string>
     <string name="abbrev_month_year">%b %Y</string>
     <string name="time1_time2">du %1$s au %2$s</string>
     <string name="date1_date2">du %2$s au %5$s</string>
diff --git a/core/res/res/values-fr-rCH/donottranslate-cldr.xml b/core/res/res/values-fr-rCH/donottranslate-cldr.xml
index 0a9835f..48db6b8 100644
--- a/core/res/res/values-fr-rCH/donottranslate-cldr.xml
+++ b/core/res/res/values-fr-rCH/donottranslate-cldr.xml
@@ -109,7 +109,7 @@
     <string name="month">%-B</string>
     <string name="month_year">%B %Y</string>
     <string name="abbrev_month_day">%-e %b</string>
-    <string name="abbrev_month">%-b</string>
+    <string name="abbrev_month">%b</string>
     <string name="abbrev_month_year">%b %Y</string>
     <string name="time1_time2">du %1$s au %2$s</string>
     <string name="date1_date2">du %2$s au %5$s</string>
@@ -117,29 +117,29 @@
     <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s - %6$s, %8$s.%7$s</string>
     <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">du %5$s %1$s %3$s/%2$s/%4$s au %10$s %6$s %8$s/%7$s/%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">du %5$s %3$s/%2$s au %10$s %8$s/%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">du %5$s %1$s %3$s/%2$s au %10$s %6$s %8$s/%7$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">du %5$s %1$s, %3$s.%2$s.%4$s au %10$s %6$s, %8$s.%7$s.%9$s</string>
+    <string name="numeric_md1_time1_md2_time2">du %5$s %3$s.%2$s au %10$s %8$s.%7$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">du %5$s %1$s, %3$s.%2$s au %10$s %6$s, %8$s.%7$s</string>
     <string name="numeric_mdy1_time1_mdy2_time2">du %5$s %3$s.%2$s.%4$s au %10$s %8$s.%7$s.%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">du %3$s %1$s %2$s au %6$s %4$s %5$s</string>
-    <string name="wday1_date1_wday2_date2">du %1$s %2$s au %4$s %5$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">du %3$s %1$s, %2$s au %6$s %4$s, %5$s</string>
+    <string name="wday1_date1_wday2_date2">du %1$s, %2$s au %4$s, %5$s</string>
     <string name="date1_time1_date2_time2">du %3$s %2$s au %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s %3$s</string>
-    <string name="wday_date">%2$s %3$s</string>
+    <string name="time_wday_date">%1$s %2$s, %3$s</string>
+    <string name="wday_date">%2$s, %3$s</string>
     <string name="time_wday">%1$s %2$s</string>
     <string name="same_year_md1_md2">du %3$s %2$s au %8$s %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">du %1$s %3$s %2$s au %6$s %8$s %7$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">du %1$s, %3$s %2$s au %6$s, %8$s %7$s</string>
     <string name="same_year_md1_time1_md2_time2">du %5$s %3$s %2$s au %10$s %8$s %7$s</string>
     <string name="same_month_md1_time1_md2_time2">du %5$s %3$s %2$s au %10$s %8$s %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">du %5$s %1$s %3$s %2$s au %10$s %6$s %8$s %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">du %5$s %1$s %3$s %2$s au %10$s %6$s %8$s %7$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">du %5$s %1$s, %3$s %2$s au %10$s %6$s, %8$s %7$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">du %5$s %1$s, %3$s %2$s au %10$s %6$s, %8$s %7$s</string>
     <string name="same_year_mdy1_time1_mdy2_time2">du %5$s %3$s %2$s %4$s au %10$s %8$s %7$s %9$s</string>
     <string name="same_month_mdy1_time1_mdy2_time2">du %5$s %3$s %2$s %4$s au %10$s %8$s %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">du %5$s %1$s %3$s %2$s %4$s au %10$s %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">du %5$s %1$s %3$s %2$s %4$s au %10$s %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">du %1$s %3$s %2$s %4$s au %6$s %8$s %7$s %9$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">du %5$s %1$s, %3$s %2$s %4$s au %10$s %6$s, %8$s %7$s %9$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">du %5$s %1$s, %3$s %2$s %4$s au %10$s %6$s, %8$s %7$s %9$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">du %1$s, %3$s %2$s %4$s au %6$s, %8$s %7$s %9$s</string>
     <string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">du %1$s %3$s %2$s au %6$s %8$s %7$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">du %1$s, %3$s %2$s au %6$s, %8$s %7$s</string>
     <string name="same_year_mdy1_mdy2">%3$s %2$s au %8$s %7$s %9$s</string>
     <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s au %6$s, %8$s %7$s %9$s</string>
diff --git a/core/res/res/values-hi-rIN/donottranslate-cldr.xml b/core/res/res/values-hi-rIN/donottranslate-cldr.xml
index 03da515..2a19da4 100644
--- a/core/res/res/values-hi-rIN/donottranslate-cldr.xml
+++ b/core/res/res/values-hi-rIN/donottranslate-cldr.xml
@@ -107,7 +107,7 @@
     <string name="abbrev_month_day_year">%d-%m-%Y</string>
     <string name="month_day">%-e %B</string>
     <string name="month">%-B</string>
-    <string name="month_year">%Y %B</string>
+    <string name="month_year">%B %Y</string>
     <string name="abbrev_month_day">%-e %b</string>
     <string name="abbrev_month">%-b</string>
     <string name="abbrev_month_year">%b %Y</string>
diff --git a/core/res/res/values-hu-rHU/donottranslate-cldr.xml b/core/res/res/values-hu-rHU/donottranslate-cldr.xml
index b56f520..08a70b8 100644
--- a/core/res/res/values-hu-rHU/donottranslate-cldr.xml
+++ b/core/res/res/values-hu-rHU/donottranslate-cldr.xml
@@ -107,17 +107,17 @@
     <string name="abbrev_month_day_year">%Y.%m.%d.</string>
     <string name="month_day">%B %-e.</string>
     <string name="month">%-B</string>
-    <string name="month_year">%Y %B</string>
+    <string name="month_year">%Y. %B</string>
     <string name="abbrev_month_day">%b %-e.</string>
     <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%Y %b</string>
+    <string name="abbrev_month_year">%Y. %b</string>
     <string name="time1_time2">%1$s - %2$s</string>
     <string name="date1_date2">%2$s - %5$s</string>
     <string name="numeric_md1_md2">%2$s.%3$s. - %7$s.%8$s.</string>
     <string name="numeric_wday1_md1_wday2_md2">%2$s.%3$s., %1$s - %7$s.%8$s., %6$s</string>
     <string name="numeric_mdy1_mdy2">%4$s.%2$s.%3$s. - %9$s.%7$s.%8$s.</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%4$s.%2$s.%3$s., %1$s - %9$s.%7$s.%8$s., %6$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s - %10$s %6$s, %9$s-%7$s-%8$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s.%2$s.%3$s., %1$s - %10$s %9$s.%7$s.%8$s., %6$s</string>
     <string name="numeric_md1_time1_md2_time2">%5$s %2$s. %3$s. - %10$s %7$s. %8$s.</string>
     <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %2$s. %3$s., %1$s - %10$s %7$s. %8$s., %6$s</string>
     <string name="numeric_mdy1_time1_mdy2_time2">%5$s %4$s.%2$s.%3$s. - %10$s %9$s.%7$s.%8$s.</string>
@@ -128,18 +128,18 @@
     <string name="wday_date">%3$s, %2$s</string>
     <string name="time_wday">%1$s %2$s</string>
     <string name="same_year_md1_md2">%2$s %3$s. - %7$s %8$s.</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %2$s %3$s - %6$s %7$s %8$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%2$s %3$s., %1$s - %7$s %8$s., %6$s</string>
     <string name="same_year_md1_time1_md2_time2">%5$s %2$s %3$s. - %10$s %7$s %8$s.</string>
     <string name="same_month_md1_time1_md2_time2">%5$s %2$s %3$s. - %10$s %7$s %8$s.</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s - %10$s %6$s %7$s %8$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s - %10$s %6$s %7$s %8$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %2$s %3$s., %1$s - %10$s %7$s %8$s., %6$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %2$s %3$s., %1$s - %10$s %7$s %8$s., %6$s</string>
     <string name="same_year_mdy1_time1_mdy2_time2">%5$s %4$s. %2$s %3$s. - %10$s %9$s. %7$s %8$s.</string>
     <string name="same_month_mdy1_time1_mdy2_time2">%5$s %4$s. %2$s %3$s. - %10$s %9$s. %7$s %8$s.</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s - %10$s %6$s, %9$s %7$s %8$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s - %10$s %6$s, %9$s %7$s %8$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %4$s %2$s %3$s - %6$s, %9$s %7$s %8$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s. %2$s %3$s., %1$s - %10$s %9$s. %7$s %8$s., %6$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s. %2$s %3$s., %1$s - %10$s %9$s. %7$s %8$s., %6$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%4$s. %2$s %3$s., %1$s - %9$s. %7$s %8$s., %6$s</string>
     <string name="same_month_md1_md2">%2$s %3$s-%8$s.</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %2$s %3$s - %6$s %7$s %8$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%2$s %3$s., %1$s - %7$s %8$s., %6$s</string>
     <string name="same_year_mdy1_mdy2">%9$s. %2$s %3$s. - %7$s %8$s.</string>
     <string name="same_month_mdy1_mdy2">%9$s. %2$s %3$s-%8$s.</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s. %2$s %3$s., %1$s - %7$s %8$s., %6$s</string>
diff --git a/core/res/res/values-id-rID/donottranslate-cldr.xml b/core/res/res/values-id-rID/donottranslate-cldr.xml
index 22860a7..6adec84 100644
--- a/core/res/res/values-id-rID/donottranslate-cldr.xml
+++ b/core/res/res/values-id-rID/donottranslate-cldr.xml
@@ -107,7 +107,7 @@
     <string name="abbrev_month_day_year">%-e %b %Y</string>
     <string name="month_day">%B %-e</string>
     <string name="month">%-B</string>
-    <string name="month_year">%Y %B</string>
+    <string name="month_year">%B %Y</string>
     <string name="abbrev_month_day">%b %-e</string>
     <string name="abbrev_month">%-b</string>
     <string name="abbrev_month_year">%Y %b</string>
diff --git a/core/res/res/values-it-rCH/donottranslate-cldr.xml b/core/res/res/values-it-rCH/donottranslate-cldr.xml
index 6d9b550..12170d6c 100644
--- a/core/res/res/values-it-rCH/donottranslate-cldr.xml
+++ b/core/res/res/values-it-rCH/donottranslate-cldr.xml
@@ -8,6 +8,11 @@
     <string name="month_long_standalone_may">Maggio</string>
     <string name="month_long_standalone_june">Giugno</string>
     <string name="month_long_standalone_july">Luglio</string>
+    <string name="month_long_standalone_august">Agosto</string>
+    <string name="month_long_standalone_september">Settembre</string>
+    <string name="month_long_standalone_october">Ottobre</string>
+    <string name="month_long_standalone_november">Novembre</string>
+    <string name="month_long_standalone_december">Dicembre</string>
 
     <string name="month_long_january">gennaio</string>
     <string name="month_long_february">febbraio</string>
@@ -15,7 +20,7 @@
     <string name="month_long_april">aprile</string>
     <string name="month_long_may">maggio</string>
     <string name="month_long_june">giugno</string>
-    <string name="month_long_july">Luglio</string>
+    <string name="month_long_july">luglio</string>
     <string name="month_long_august">agosto</string>
     <string name="month_long_september">settembre</string>
     <string name="month_long_october">ottobre</string>
@@ -112,29 +117,29 @@
     <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s - %6$s, %8$s.%7$s</string>
     <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s - %8$s.%7$s.%9$s</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s - %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s-%2$s-%4$s - %10$s %6$s, %8$s-%7$s-%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s/%2$s - %10$s %8$s/%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s/%2$s - %10$s %6$s %8$s/%7$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s - %10$s %6$s, %8$s.%7$s.%9$s</string>
+    <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s - %10$s %8$s.%7$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s - %10$s %6$s, %8$s.%7$s</string>
     <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s - %10$s %8$s.%7$s.%9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s - %6$s %4$s %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s - %6$s %4$s, %5$s</string>
+    <string name="wday1_date1_wday2_date2">%1$s, %2$s - %4$s, %5$s</string>
     <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s %3$s</string>
-    <string name="wday_date">%2$s %3$s</string>
+    <string name="time_wday_date">%1$s %2$s, %3$s</string>
+    <string name="wday_date">%2$s, %3$s</string>
     <string name="time_wday">%1$s %2$s</string>
     <string name="same_year_md1_md2">%3$s %2$s - %8$s %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s, %3$s %2$s - %6$s, %8$s %7$s</string>
     <string name="same_year_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
     <string name="same_month_md1_time1_md2_time2">%5$s %3$s %2$s - %10$s %8$s %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s - %10$s %6$s %8$s %7$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s %2$s - %10$s %6$s %8$s %7$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s %2$s - %10$s %6$s, %8$s %7$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s %2$s - %10$s %6$s, %8$s %7$s</string>
     <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
     <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s %2$s %4$s - %10$s %8$s %7$s %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s %2$s %4$s - %10$s %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s %2$s %4$s - %10$s %6$s %8$s %7$s %9$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s %3$s %2$s %4$s - %6$s %8$s %7$s %9$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s - %10$s %6$s, %8$s %7$s %9$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s %2$s %4$s - %10$s %6$s, %8$s %7$s %9$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s %4$s - %6$s, %8$s %7$s %9$s</string>
     <string name="same_month_md1_md2">%3$s-%8$s %2$s</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %3$s %2$s - %6$s %8$s %7$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s, %3$s %2$s - %6$s, %8$s %7$s</string>
     <string name="same_year_mdy1_mdy2">%3$s %2$s - %8$s %7$s %9$s</string>
     <string name="same_month_mdy1_mdy2">%3$s-%8$s %2$s %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s, %3$s %2$s - %6$s, %8$s %7$s %9$s</string>
diff --git a/core/res/res/values-it-rIT/donottranslate-cldr.xml b/core/res/res/values-it-rIT/donottranslate-cldr.xml
index 1bf7992..2178bbe 100644
--- a/core/res/res/values-it-rIT/donottranslate-cldr.xml
+++ b/core/res/res/values-it-rIT/donottranslate-cldr.xml
@@ -8,6 +8,11 @@
     <string name="month_long_standalone_may">Maggio</string>
     <string name="month_long_standalone_june">Giugno</string>
     <string name="month_long_standalone_july">Luglio</string>
+    <string name="month_long_standalone_august">Agosto</string>
+    <string name="month_long_standalone_september">Settembre</string>
+    <string name="month_long_standalone_october">Ottobre</string>
+    <string name="month_long_standalone_november">Novembre</string>
+    <string name="month_long_standalone_december">Dicembre</string>
 
     <string name="month_long_january">gennaio</string>
     <string name="month_long_february">febbraio</string>
@@ -15,7 +20,7 @@
     <string name="month_long_april">aprile</string>
     <string name="month_long_may">maggio</string>
     <string name="month_long_june">giugno</string>
-    <string name="month_long_july">Luglio</string>
+    <string name="month_long_july">luglio</string>
     <string name="month_long_august">agosto</string>
     <string name="month_long_september">settembre</string>
     <string name="month_long_october">ottobre</string>
@@ -112,7 +117,7 @@
     <string name="numeric_wday1_md1_wday2_md2">%1$s %3$s/%2$s - %6$s %8$s/%7$s</string>
     <string name="numeric_mdy1_mdy2">%3$s/%2$s/%4$s - %8$s/%7$s/%9$s</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %3$s/%2$s/%4$s - %6$s %8$s/%7$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s-%2$s-%4$s - %10$s %6$s, %8$s-%7$s-%9$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s/%2$s/%4$s - %10$s %6$s, %8$s/%7$s/%9$s</string>
     <string name="numeric_md1_time1_md2_time2">%5$s %3$s/%2$s - %10$s %8$s/%7$s</string>
     <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s/%2$s - %10$s %6$s %8$s/%7$s</string>
     <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s/%2$s/%4$s - %10$s %8$s/%7$s/%9$s</string>
diff --git a/core/res/res/values-it/donottranslate-cldr.xml b/core/res/res/values-it/donottranslate-cldr.xml
index 1bf7992..2178bbe 100644
--- a/core/res/res/values-it/donottranslate-cldr.xml
+++ b/core/res/res/values-it/donottranslate-cldr.xml
@@ -8,6 +8,11 @@
     <string name="month_long_standalone_may">Maggio</string>
     <string name="month_long_standalone_june">Giugno</string>
     <string name="month_long_standalone_july">Luglio</string>
+    <string name="month_long_standalone_august">Agosto</string>
+    <string name="month_long_standalone_september">Settembre</string>
+    <string name="month_long_standalone_october">Ottobre</string>
+    <string name="month_long_standalone_november">Novembre</string>
+    <string name="month_long_standalone_december">Dicembre</string>
 
     <string name="month_long_january">gennaio</string>
     <string name="month_long_february">febbraio</string>
@@ -15,7 +20,7 @@
     <string name="month_long_april">aprile</string>
     <string name="month_long_may">maggio</string>
     <string name="month_long_june">giugno</string>
-    <string name="month_long_july">Luglio</string>
+    <string name="month_long_july">luglio</string>
     <string name="month_long_august">agosto</string>
     <string name="month_long_september">settembre</string>
     <string name="month_long_october">ottobre</string>
@@ -112,7 +117,7 @@
     <string name="numeric_wday1_md1_wday2_md2">%1$s %3$s/%2$s - %6$s %8$s/%7$s</string>
     <string name="numeric_mdy1_mdy2">%3$s/%2$s/%4$s - %8$s/%7$s/%9$s</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %3$s/%2$s/%4$s - %6$s %8$s/%7$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s-%2$s-%4$s - %10$s %6$s, %8$s-%7$s-%9$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s/%2$s/%4$s - %10$s %6$s, %8$s/%7$s/%9$s</string>
     <string name="numeric_md1_time1_md2_time2">%5$s %3$s/%2$s - %10$s %8$s/%7$s</string>
     <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s/%2$s - %10$s %6$s %8$s/%7$s</string>
     <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s/%2$s/%4$s - %10$s %8$s/%7$s/%9$s</string>
diff --git a/core/res/res/values-ja-rJP/donottranslate-cldr.xml b/core/res/res/values-ja-rJP/donottranslate-cldr.xml
index 10f2f79..d2510f6 100644
--- a/core/res/res/values-ja-rJP/donottranslate-cldr.xml
+++ b/core/res/res/values-ja-rJP/donottranslate-cldr.xml
@@ -138,10 +138,10 @@
     <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s年%2$s%3$s日(%1$s)~%10$s %9$s年%7$s%8$s日(%6$s)</string>
     <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s年%2$s%3$s日(%1$s)~%10$s %9$s年%7$s%8$s日(%6$s)</string>
     <string name="same_month_wday1_mdy1_wday2_mdy2">%4$s年%2$s%3$s日(%1$s)~%9$s年%7$s%8$s日(%6$s)</string>
-    <string name="same_month_md1_md2">%2$s月%3$s日~%8$s日</string>
+    <string name="same_month_md1_md2">%2$s%3$s日~%8$s日</string>
     <string name="same_month_wday1_md1_wday2_md2">%2$s%3$s日(%1$s)~%7$s%8$s日(%6$s)</string>
-    <string name="same_year_mdy1_mdy2">%9$s年%2$s%3$s日~%7$s月%8$s日</string>
+    <string name="same_year_mdy1_mdy2">%9$s年%2$s%3$s日~%7$s%8$s日</string>
     <string name="same_month_mdy1_mdy2">%9$s年%2$s%3$s日~%8$s日</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s年%2$s%3$s日(%1$s)~%7$s月%8$s日(%6$s)</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s年%2$s%3$s日(%1$s)~%7$s%8$s日(%6$s)</string>
     <string name="short_format_month">%b</string>
 </resources>
diff --git a/core/res/res/values-ja/donottranslate-cldr.xml b/core/res/res/values-ja/donottranslate-cldr.xml
index 10f2f79..d2510f6 100644
--- a/core/res/res/values-ja/donottranslate-cldr.xml
+++ b/core/res/res/values-ja/donottranslate-cldr.xml
@@ -138,10 +138,10 @@
     <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s年%2$s%3$s日(%1$s)~%10$s %9$s年%7$s%8$s日(%6$s)</string>
     <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s年%2$s%3$s日(%1$s)~%10$s %9$s年%7$s%8$s日(%6$s)</string>
     <string name="same_month_wday1_mdy1_wday2_mdy2">%4$s年%2$s%3$s日(%1$s)~%9$s年%7$s%8$s日(%6$s)</string>
-    <string name="same_month_md1_md2">%2$s月%3$s日~%8$s日</string>
+    <string name="same_month_md1_md2">%2$s%3$s日~%8$s日</string>
     <string name="same_month_wday1_md1_wday2_md2">%2$s%3$s日(%1$s)~%7$s%8$s日(%6$s)</string>
-    <string name="same_year_mdy1_mdy2">%9$s年%2$s%3$s日~%7$s月%8$s日</string>
+    <string name="same_year_mdy1_mdy2">%9$s年%2$s%3$s日~%7$s%8$s日</string>
     <string name="same_month_mdy1_mdy2">%9$s年%2$s%3$s日~%8$s日</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s年%2$s%3$s日(%1$s)~%7$s月%8$s日(%6$s)</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s年%2$s%3$s日(%1$s)~%7$s%8$s日(%6$s)</string>
     <string name="short_format_month">%b</string>
 </resources>
diff --git a/core/res/res/values-ko-rKR/donottranslate-cldr.xml b/core/res/res/values-ko-rKR/donottranslate-cldr.xml
index 45ca90a..57cd356 100644
--- a/core/res/res/values-ko-rKR/donottranslate-cldr.xml
+++ b/core/res/res/values-ko-rKR/donottranslate-cldr.xml
@@ -126,10 +126,10 @@
     <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s년 %2$s %3$s일 %1$s – %10$s %9$s년 %7$s %8$s일 %6$s</string>
     <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s년 %2$s %3$s일 %1$s – %10$s %9$s년 %7$s %8$s일 %6$s</string>
     <string name="same_month_wday1_mdy1_wday2_mdy2">%4$s년 %2$s %3$s일 %1$s – %9$s년 %7$s %8$s일 %6$s</string>
-    <string name="same_month_md1_md2">%2$s월 %3$s일 ~ %8$s일</string>
+    <string name="same_month_md1_md2">%2$s %3$s일 ~ %8$s일</string>
     <string name="same_month_wday1_md1_wday2_md2">%2$s %3$s일 (%1$s) – %7$s %8$s일 (%6$s)</string>
-    <string name="same_year_mdy1_mdy2">%9$s년 %2$s %3$s일 ~ %7$s월 %8$s일</string>
+    <string name="same_year_mdy1_mdy2">%9$s년 %2$s %3$s일 ~ %7$s %8$s일</string>
     <string name="same_month_mdy1_mdy2">%9$s년 %2$s %3$s일~%8$s일</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s년 %2$s %3$s일 %1$s ~ %7$s월 %8$s일 %6$s</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s년 %2$s %3$s일 %1$s ~ %7$s %8$s일 %6$s</string>
     <string name="short_format_month">%b</string>
 </resources>
diff --git a/core/res/res/values-ko/donottranslate-cldr.xml b/core/res/res/values-ko/donottranslate-cldr.xml
index 45ca90a..57cd356 100644
--- a/core/res/res/values-ko/donottranslate-cldr.xml
+++ b/core/res/res/values-ko/donottranslate-cldr.xml
@@ -126,10 +126,10 @@
     <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s년 %2$s %3$s일 %1$s – %10$s %9$s년 %7$s %8$s일 %6$s</string>
     <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s년 %2$s %3$s일 %1$s – %10$s %9$s년 %7$s %8$s일 %6$s</string>
     <string name="same_month_wday1_mdy1_wday2_mdy2">%4$s년 %2$s %3$s일 %1$s – %9$s년 %7$s %8$s일 %6$s</string>
-    <string name="same_month_md1_md2">%2$s월 %3$s일 ~ %8$s일</string>
+    <string name="same_month_md1_md2">%2$s %3$s일 ~ %8$s일</string>
     <string name="same_month_wday1_md1_wday2_md2">%2$s %3$s일 (%1$s) – %7$s %8$s일 (%6$s)</string>
-    <string name="same_year_mdy1_mdy2">%9$s년 %2$s %3$s일 ~ %7$s월 %8$s일</string>
+    <string name="same_year_mdy1_mdy2">%9$s년 %2$s %3$s일 ~ %7$s %8$s일</string>
     <string name="same_month_mdy1_mdy2">%9$s년 %2$s %3$s일~%8$s일</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s년 %2$s %3$s일 %1$s ~ %7$s월 %8$s일 %6$s</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s년 %2$s %3$s일 %1$s ~ %7$s %8$s일 %6$s</string>
     <string name="short_format_month">%b</string>
 </resources>
diff --git a/core/res/res/values-lt-rLT/donottranslate-cldr.xml b/core/res/res/values-lt-rLT/donottranslate-cldr.xml
index 636a180..20d58e0 100644
--- a/core/res/res/values-lt-rLT/donottranslate-cldr.xml
+++ b/core/res/res/values-lt-rLT/donottranslate-cldr.xml
@@ -108,38 +108,38 @@
     <string name="month_day">%B %-e</string>
     <string name="month">%-B</string>
     <string name="month_year">%Y %B</string>
-    <string name="abbrev_month_day">%b %-e</string>
-    <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%Y %b</string>
+    <string name="abbrev_month_day">%b %-e d.</string>
+    <string name="abbrev_month">%b</string>
+    <string name="abbrev_month_year">%Y m. %b</string>
     <string name="time1_time2">%1$s - %2$s</string>
     <string name="date1_date2">%2$s - %5$s</string>
     <string name="numeric_md1_md2">%2$s-%3$s - %7$s-%8$s</string>
     <string name="numeric_wday1_md1_wday2_md2">%2$s-%3$s%1$s - %7$s-%8$s%6$s</string>
     <string name="numeric_mdy1_mdy2">%4$s-%2$s-%3$s - %9$s-%7$s-%8$s</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%4$s-%2$s-%3$s%1$s - %9$s-%7$s-%8$s%6$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s - %10$s %6$s, %9$s-%7$s-%8$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s-%2$s-%3$s%1$s - %10$s %9$s-%7$s-%8$s%6$s</string>
     <string name="numeric_md1_time1_md2_time2">%5$s %2$s-%3$s - %10$s %7$s-%8$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %2$s-%3$s - %10$s %6$s, %7$s-%8$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %2$s-%3$s%1$s - %10$s %7$s-%8$s%6$s</string>
     <string name="numeric_mdy1_time1_mdy2_time2">%5$s %4$s-%2$s-%3$s - %10$s %9$s-%7$s-%8$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s - %6$s %4$s %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %2$s%1$s - %6$s %5$s%4$s</string>
+    <string name="wday1_date1_wday2_date2">%2$s%1$s - %5$s%4$s</string>
     <string name="date1_time1_date2_time2">%3$s %2$s - %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s %3$s</string>
-    <string name="wday_date">%2$s %3$s</string>
+    <string name="time_wday_date">%1$s %3$s%2$s</string>
+    <string name="wday_date">%3$s%2$s</string>
     <string name="time_wday">%1$s %2$s</string>
     <string name="same_year_md1_md2">%2$s %3$s - %7$s %8$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %2$s %3$s - %6$s %7$s %8$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%2$s %3$s d.%1$s - %7$s %8$s d.%6$s</string>
     <string name="same_year_md1_time1_md2_time2">%5$s %2$s %3$s - %10$s %7$s %8$s</string>
     <string name="same_month_md1_time1_md2_time2">%5$s %2$s %3$s - %10$s %7$s %8$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s - %10$s %6$s %7$s %8$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s - %10$s %6$s %7$s %8$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %2$s %3$s d.%1$s - %10$s %7$s %8$s d.%6$s</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %2$s %3$s d.%1$s - %10$s %7$s %8$s d.%6$s</string>
     <string name="same_year_mdy1_time1_mdy2_time2">%5$s %4$s m. %2$s %3$s d. - %10$s %9$s m. %7$s %8$s d.</string>
     <string name="same_month_mdy1_time1_mdy2_time2">%5$s %4$s m. %2$s %3$s d. - %10$s %9$s m. %7$s %8$s d.</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s - %10$s %6$s, %9$s %7$s %8$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s - %10$s %6$s, %9$s %7$s %8$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %4$s %2$s %3$s - %6$s, %9$s %7$s %8$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s m. %2$s %3$s d.,%1$s - %10$s %9$s m. %7$s %8$s d.,%6$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s m. %2$s %3$s d.,%1$s - %10$s %9$s m. %7$s %8$s d.,%6$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%4$s m. %2$s %3$s d.,%1$s - %9$s m. %7$s %8$s d.,%6$s</string>
     <string name="same_month_md1_md2">%2$s %3$s d.-%8$s d.</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %2$s %3$s - %6$s %7$s %8$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%2$s %3$s d.%1$s - %7$s %8$s d.%6$s</string>
     <string name="same_year_mdy1_mdy2">%9$s m. %2$s %3$s d. - %7$s %8$s d.</string>
     <string name="same_month_mdy1_mdy2">%9$s m. %2$s %3$s d.-%8$s d.</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s m. %2$s %3$s d.,%1$s - %7$s %8$s d.,%6$s</string>
diff --git a/core/res/res/values-nl-rBE/donottranslate-cldr.xml b/core/res/res/values-nl-rBE/donottranslate-cldr.xml
index 5b4cbf7..680a392 100644
--- a/core/res/res/values-nl-rBE/donottranslate-cldr.xml
+++ b/core/res/res/values-nl-rBE/donottranslate-cldr.xml
@@ -117,9 +117,9 @@
     <string name="numeric_wday1_md1_wday2_md2">%1$s %3$s/%2$s - %6$s %8$s/%7$s</string>
     <string name="numeric_mdy1_mdy2">%3$s/%2$s/%4$s - %8$s/%7$s/%9$s</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s %3$s/%2$s/%4$s - %6$s %8$s/%7$s/%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s-%2$s-%4$s - %10$s %6$s %8$s-%7$s-%9$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %3$s-%2$s - %10$s %8$s-%7$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s-%2$s - %10$s %6$s %8$s-%7$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s %3$s/%2$s/%4$s - %10$s %6$s %8$s/%7$s/%9$s</string>
+    <string name="numeric_md1_time1_md2_time2">%5$s %3$s/%2$s - %10$s %8$s/%7$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %3$s/%2$s - %10$s %6$s %8$s/%7$s</string>
     <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s/%2$s/%4$s - %10$s %8$s/%7$s/%9$s</string>
     <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s - %6$s %4$s %5$s</string>
     <string name="wday1_date1_wday2_date2">%1$s %2$s - %4$s %5$s</string>
diff --git a/core/res/res/values-pt-rPT/donottranslate-cldr.xml b/core/res/res/values-pt-rPT/donottranslate-cldr.xml
index be0fdb7..f38a2d0 100644
--- a/core/res/res/values-pt-rPT/donottranslate-cldr.xml
+++ b/core/res/res/values-pt-rPT/donottranslate-cldr.xml
@@ -109,7 +109,7 @@
     <string name="month">%-B</string>
     <string name="month_year">%B de %Y</string>
     <string name="abbrev_month_day">%-e de %b</string>
-    <string name="abbrev_month">%-b</string>
+    <string name="abbrev_month">%b</string>
     <string name="abbrev_month_year">%b de %Y</string>
     <string name="time1_time2">%1$s - %2$s</string>
     <string name="date1_date2">%2$s - %5$s</string>
diff --git a/core/res/res/values-sk-rSK/donottranslate-cldr.xml b/core/res/res/values-sk-rSK/donottranslate-cldr.xml
index 2b3c6d9..16239df 100644
--- a/core/res/res/values-sk-rSK/donottranslate-cldr.xml
+++ b/core/res/res/values-sk-rSK/donottranslate-cldr.xml
@@ -109,7 +109,7 @@
     <string name="month">%-B</string>
     <string name="month_year">%B %Y</string>
     <string name="abbrev_month_day">%-e. %b</string>
-    <string name="abbrev_month">%-b</string>
+    <string name="abbrev_month">%b</string>
     <string name="abbrev_month_year">%b %Y</string>
     <string name="time1_time2">%1$s - %2$s</string>
     <string name="date1_date2">%2$s - %5$s</string>
diff --git a/core/res/res/values-sl-rSI/donottranslate-cldr.xml b/core/res/res/values-sl-rSI/donottranslate-cldr.xml
index 2b2b9c3..b4ea32f 100644
--- a/core/res/res/values-sl-rSI/donottranslate-cldr.xml
+++ b/core/res/res/values-sl-rSI/donottranslate-cldr.xml
@@ -107,39 +107,39 @@
     <string name="abbrev_month_day_year">%-e. %b. %Y</string>
     <string name="month_day">%-e. %B</string>
     <string name="month">%-B</string>
-    <string name="month_year">%Y %B</string>
-    <string name="abbrev_month_day">%b %-e</string>
-    <string name="abbrev_month">%-b</string>
-    <string name="abbrev_month_year">%Y %b</string>
+    <string name="month_year">%B %Y</string>
+    <string name="abbrev_month_day">%-e. %b.</string>
+    <string name="abbrev_month">%b</string>
+    <string name="abbrev_month_year">%b. %Y</string>
     <string name="time1_time2">%1$s – %2$s</string>
     <string name="date1_date2">%2$s – %5$s</string>
     <string name="numeric_md1_md2">%3$s. %2$s. – %8$s. %7$s.</string>
     <string name="numeric_wday1_md1_wday2_md2">%1$s., %3$s. %2$s. – %6$s., %8$s. %7$s.</string>
     <string name="numeric_mdy1_mdy2">%3$s. %2$s. %4$s – %8$s. %7$s. %9$s</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s., %3$s. %2$s. %4$s – %6$s., %8$s. %7$s. %9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s – %10$s %6$s, %9$s-%7$s-%8$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s., %3$s. %2$s. %4$s – %10$s %6$s., %8$s. %7$s. %9$s</string>
     <string name="numeric_md1_time1_md2_time2">%5$s %3$s. %2$s. – %10$s %8$s. %7$s.</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %2$s-%3$s – %10$s %6$s, %7$s-%8$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s., %3$s. %2$s. – %10$s %6$s., %8$s. %7$s.</string>
     <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s. %4$s – %10$s %8$s. %7$s. %9$s</string>
-    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s %2$s – %6$s %4$s %5$s</string>
-    <string name="wday1_date1_wday2_date2">%1$s %2$s – %4$s %5$s</string>
+    <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s., %2$s – %6$s %4$s., %5$s</string>
+    <string name="wday1_date1_wday2_date2">%1$s., %2$s – %4$s., %5$s</string>
     <string name="date1_time1_date2_time2">%3$s %2$s – %6$s %5$s</string>
-    <string name="time_wday_date">%1$s %2$s %3$s</string>
-    <string name="wday_date">%2$s %3$s</string>
+    <string name="time_wday_date">%1$s %2$s., %3$s</string>
+    <string name="wday_date">%2$s., %3$s</string>
     <string name="time_wday">%1$s %2$s</string>
     <string name="same_year_md1_md2">%3$s. %2$s – %8$s. %7$s</string>
-    <string name="same_year_wday1_md1_wday2_md2">%1$s %2$s %3$s – %6$s %7$s %8$s</string>
+    <string name="same_year_wday1_md1_wday2_md2">%1$s., %3$s. %2$s. – %6$s., %8$s. %7$s.</string>
     <string name="same_year_md1_time1_md2_time2">%5$s %3$s. %2$s – %10$s %8$s. %7$s</string>
     <string name="same_month_md1_time1_md2_time2">%5$s %3$s. %2$s – %10$s %8$s. %7$s</string>
-    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s – %10$s %6$s %7$s %8$s</string>
-    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s %2$s %3$s – %10$s %6$s %7$s %8$s</string>
+    <string name="same_year_wday1_md1_time1_wday2_md2_time2">%5$s %1$s., %3$s. %2$s. – %10$s %6$s., %8$s. %7$s.</string>
+    <string name="same_month_wday1_md1_time1_wday2_md2_time2">%5$s %1$s., %3$s. %2$s. – %10$s %6$s., %8$s. %7$s.</string>
     <string name="same_year_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s. %4$s – %10$s %8$s. %7$s. %9$s</string>
     <string name="same_month_mdy1_time1_mdy2_time2">%5$s %3$s. %2$s. %4$s – %10$s %8$s. %7$s. %9$s</string>
-    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s – %10$s %6$s, %9$s %7$s %8$s</string>
-    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s %2$s %3$s – %10$s %6$s, %9$s %7$s %8$s</string>
-    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s, %4$s %2$s %3$s – %6$s, %9$s %7$s %8$s</string>
+    <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s., %3$s. %2$s. %4$s – %10$s %6$s., %8$s. %7$s. %9$s</string>
+    <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s., %3$s. %2$s. %4$s – %10$s %6$s., %8$s. %7$s. %9$s</string>
+    <string name="same_month_wday1_mdy1_wday2_mdy2">%1$s., %3$s. %2$s. %4$s – %6$s., %8$s. %7$s. %9$s</string>
     <string name="same_month_md1_md2">%3$s.–%8$s. %2$s.</string>
-    <string name="same_month_wday1_md1_wday2_md2">%1$s %2$s %3$s – %6$s %7$s %8$s</string>
+    <string name="same_month_wday1_md1_wday2_md2">%1$s., %3$s. %2$s. – %6$s., %8$s. %7$s.</string>
     <string name="same_year_mdy1_mdy2">%3$s. %2$s. – %8$s. %7$s. %9$s</string>
     <string name="same_month_mdy1_mdy2">%3$s.–%8$s. %2$s. %9$s</string>
     <string name="same_year_wday1_mdy1_wday2_mdy2">%1$s., %3$s. %2$s. – %6$s., %8$s. %7$s. %9$s</string>
diff --git a/core/res/res/values-uk-rUA/donottranslate-cldr.xml b/core/res/res/values-uk-rUA/donottranslate-cldr.xml
index 55d3983..c51f8d1 100644
--- a/core/res/res/values-uk-rUA/donottranslate-cldr.xml
+++ b/core/res/res/values-uk-rUA/donottranslate-cldr.xml
@@ -117,9 +117,9 @@
     <string name="numeric_wday1_md1_wday2_md2">%1$s, %3$s.%2$s – %6$s, %8$s.%7$s</string>
     <string name="numeric_mdy1_mdy2">%3$s.%2$s.%4$s – %8$s.%7$s.%9$s</string>
     <string name="numeric_wday1_mdy1_wday2_mdy2">%1$s, %3$s.%2$s.%4$s – %6$s, %8$s.%7$s.%9$s</string>
-    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %4$s-%2$s-%3$s – %10$s %6$s, %9$s-%7$s-%8$s</string>
-    <string name="numeric_md1_time1_md2_time2">%5$s %2$s-%3$s – %10$s %7$s-%8$s</string>
-    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %2$s-%3$s – %10$s %6$s, %7$s-%8$s</string>
+    <string name="numeric_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %1$s, %3$s.%2$s.%4$s – %10$s %6$s, %8$s.%7$s.%9$s</string>
+    <string name="numeric_md1_time1_md2_time2">%5$s %3$s.%2$s – %10$s %8$s.%7$s</string>
+    <string name="numeric_wday1_md1_time1_wday2_md2_time2">%5$s %1$s, %3$s.%2$s – %10$s %6$s, %8$s.%7$s</string>
     <string name="numeric_mdy1_time1_mdy2_time2">%5$s %3$s.%2$s.%4$s – %10$s %8$s.%7$s.%9$s</string>
     <string name="wday1_date1_time1_wday2_date2_time2">%3$s %1$s, %2$s – %6$s %4$s, %5$s</string>
     <string name="wday1_date1_wday2_date2">%1$s, %2$s – %4$s, %5$s</string>
diff --git a/core/res/res/values-vi-rVN/donottranslate-cldr.xml b/core/res/res/values-vi-rVN/donottranslate-cldr.xml
index 71178cc..72ff8b6 100644
--- a/core/res/res/values-vi-rVN/donottranslate-cldr.xml
+++ b/core/res/res/values-vi-rVN/donottranslate-cldr.xml
@@ -109,7 +109,7 @@
     <string name="month">%-B</string>
     <string name="month_year">%B %Y</string>
     <string name="abbrev_month_day">%-e %b</string>
-    <string name="abbrev_month">%-b</string>
+    <string name="abbrev_month">%b</string>
     <string name="abbrev_month_year">%b %Y</string>
     <string name="time1_time2">%1$s - %2$s</string>
     <string name="date1_date2">%2$s - %5$s</string>
diff --git a/core/res/res/values-zh-rCN/donottranslate-cldr.xml b/core/res/res/values-zh-rCN/donottranslate-cldr.xml
index 8c386a4..6d52d70 100644
--- a/core/res/res/values-zh-rCN/donottranslate-cldr.xml
+++ b/core/res/res/values-zh-rCN/donottranslate-cldr.xml
@@ -138,10 +138,10 @@
     <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s年%2$s%3$s日%1$s–%10$s %9$s年%7$s%8$s日%6$s</string>
     <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s年%2$s%3$s日%1$s–%10$s %9$s年%7$s%8$s日%6$s</string>
     <string name="same_month_wday1_mdy1_wday2_mdy2">%4$s年%2$s%3$s日%1$s–%9$s年%7$s%8$s日%6$s</string>
-    <string name="same_month_md1_md2">%2$s月%3$s日至%8$s日</string>
+    <string name="same_month_md1_md2">%2$s%3$s日至%8$s日</string>
     <string name="same_month_wday1_md1_wday2_md2">%2$s%3$s日%1$s–%7$s%8$s日%6$s</string>
-    <string name="same_year_mdy1_mdy2">%9$s年%2$s%3$s日至%7$s月%8$s日</string>
+    <string name="same_year_mdy1_mdy2">%9$s年%2$s%3$s日至%7$s%8$s日</string>
     <string name="same_month_mdy1_mdy2">%9$s年%2$s%3$s日至%8$s日</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s年%2$s%3$s日%1$s至%7$s月%8$s日%6$s</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s年%2$s%3$s日%1$s至%7$s%8$s日%6$s</string>
     <string name="short_format_month">%b</string>
 </resources>
diff --git a/core/res/res/values-zh-rTW/donottranslate-cldr.xml b/core/res/res/values-zh-rTW/donottranslate-cldr.xml
index 8c386a4..6d52d70 100644
--- a/core/res/res/values-zh-rTW/donottranslate-cldr.xml
+++ b/core/res/res/values-zh-rTW/donottranslate-cldr.xml
@@ -138,10 +138,10 @@
     <string name="same_year_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s年%2$s%3$s日%1$s–%10$s %9$s年%7$s%8$s日%6$s</string>
     <string name="same_month_wday1_mdy1_time1_wday2_mdy2_time2">%5$s %4$s年%2$s%3$s日%1$s–%10$s %9$s年%7$s%8$s日%6$s</string>
     <string name="same_month_wday1_mdy1_wday2_mdy2">%4$s年%2$s%3$s日%1$s–%9$s年%7$s%8$s日%6$s</string>
-    <string name="same_month_md1_md2">%2$s月%3$s日至%8$s日</string>
+    <string name="same_month_md1_md2">%2$s%3$s日至%8$s日</string>
     <string name="same_month_wday1_md1_wday2_md2">%2$s%3$s日%1$s–%7$s%8$s日%6$s</string>
-    <string name="same_year_mdy1_mdy2">%9$s年%2$s%3$s日至%7$s月%8$s日</string>
+    <string name="same_year_mdy1_mdy2">%9$s年%2$s%3$s日至%7$s%8$s日</string>
     <string name="same_month_mdy1_mdy2">%9$s年%2$s%3$s日至%8$s日</string>
-    <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s年%2$s%3$s日%1$s至%7$s月%8$s日%6$s</string>
+    <string name="same_year_wday1_mdy1_wday2_mdy2">%9$s年%2$s%3$s日%1$s至%7$s%8$s日%6$s</string>
     <string name="short_format_month">%b</string>
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index d778f5c..78567fc 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1998,6 +1998,16 @@
             <!-- The dropdown should fit the width of its anchor. -->
             <enum name="wrap_content" value="-2" />
         </attr>
+        <!-- Specifies the basic width of the dropdown. Its value may
+             be a dimension (such as "12dip") for a constant width, fill_parent
+             to fill the width of the screen, or wrap_content to match the height of
+             the content of the drop down. -->
+        <attr name="dropDownHeight" format="dimension">
+            <!-- The dropdown should fill the width of the screen. -->
+            <enum name="fill_parent" value="-1" />
+            <!-- The dropdown should fit the width of its anchor. -->
+            <enum name="wrap_content" value="-2" />
+        </attr>
         <attr name="inputType" />
     </declare-styleable>
     <declare-styleable name="PopupWindow">
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 41db0fa..079baf7 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1116,7 +1116,8 @@
   <public type="attr" name="allowBackup" />
   <public type="attr" name="glEsVersion" />
   <public type="attr" name="queryAfterZeroResults" />
-  
+  <public type="attr" name="dropDownHeight" />
+
   <public-padding type="attr" name="donut_resource_pad" end="0x0101029f" />
 
   <public-padding type="id" name="donut_resource_pad" end="0x01020040" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 91b6609..88464f7 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1338,6 +1338,22 @@
     <!-- Title of the WebView save password dialog.  If the user enters a password in a form on a website, a dialog will come up asking if they want to save the password. -->
     <string name="save_password_label">Confirm</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_readHistoryBookmarks">read Browser\'s history and bookmarks</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_readHistoryBookmarks">Allows the application to read all
+        the URLs that the Browser has visited, and all of the Browser\'s bookmarks.</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_writeHistoryBookmarks">write Browser\'s history and bookmarks</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_writeHistoryBookmarks">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>
+
     <!-- If the user enters a password in a form on a website, a dialog will come up asking if they want to save the password. Text in the save password dialog, asking if the browser should remember a password. -->
     <string name="save_password_message">Do you want the browser to remember this password?</string>
     <!-- If the user enters a password in a form on a website, a dialog will come up asking if they want to save the password. Button in the save password dialog, saying not to remember this password. -->
@@ -1792,15 +1808,15 @@
     <!-- External media notification strings -->
     <!-- Shown when external media is being checked -->
     <string name="ext_media_checking_notification_title">Preparing SD card</string>
-    <string name="ext_media_checking_notification_message">Checking for errors</string>
+    <string name="ext_media_checking_notification_message">Checking for errors.</string>
 
     <!-- Shown when external media is blank (or unsupported filesystem) -->
     <string name="ext_media_nofs_notification_title">Blank SD card</string>
-    <string name="ext_media_nofs_notification_message">The SD card is blank or using an unsupported filesystem.</string>
+    <string name="ext_media_nofs_notification_message">SD card blank or has unsupported filesystem.</string>
 
     <!-- Shown when external media is unmountable (corrupt)) -->
     <string name="ext_media_unmountable_notification_title">Damaged SD card</string>
-    <string name="ext_media_unmountable_notification_message">The SD card is damaged. You may have to reformat your card.</string>
+    <string name="ext_media_unmountable_notification_message">SD card damaged. You may have to reformat it.</string>
 
     <!-- Shown when external media is unsafely removed -->
     <string name="ext_media_badremoval_notification_title">SD card unexpectedly removed</string>
@@ -1808,11 +1824,11 @@
 
     <!-- Shown when external media has been safely removed -->
     <string name="ext_media_safe_unmount_notification_title">SD card safe to remove</string>
-    <string name="ext_media_safe_unmount_notification_message">The SD card can now be safely removed.</string>
+    <string name="ext_media_safe_unmount_notification_message">You can safely remove SD card.</string>
 
     <!-- Shown when external media is missing -->
     <string name="ext_media_nomedia_notification_title">Removed SD card</string>
-    <string name="ext_media_nomedia_notification_message">The SD has been removed. Insert a new SD card to increase your device storage.</string>
+    <string name="ext_media_nomedia_notification_message">SD card removed. Insert a new one.</string>
 
     <!-- Shown in LauncherActivity when the requested target Intent didn't return any matching Activities, leaving the list empty. -->
     <string name="activity_list_empty">No matching activities found</string>
diff --git a/docs/html/guide/topics/resources/res-selection-flowchart.png b/docs/html/guide/topics/resources/res-selection-flowchart.png
new file mode 100755
index 0000000..d738b3f
--- /dev/null
+++ b/docs/html/guide/topics/resources/res-selection-flowchart.png
Binary files differ
diff --git a/docs/html/guide/topics/resources/res-selection-flowchart.vsd b/docs/html/guide/topics/resources/res-selection-flowchart.vsd
new file mode 100755
index 0000000..65bfcdb
--- /dev/null
+++ b/docs/html/guide/topics/resources/res-selection-flowchart.vsd
Binary files differ
diff --git a/docs/html/guide/topics/resources/resources-i18n.jd b/docs/html/guide/topics/resources/resources-i18n.jd
old mode 100644
new mode 100755
index 4bbb44a..6900704
--- a/docs/html/guide/topics/resources/resources-i18n.jd
+++ b/docs/html/guide/topics/resources/resources-i18n.jd
@@ -1,713 +1,716 @@
-page.title=Resources and Internationalization
-parent.title=Resources and Assets
-parent.link=index.html
-@jd:body
-
-<div id="qv-wrapper">
-<div id="qv">
-
-  <h2>Key classes</h2>
-  <ol>
-    <li>{@link android.content.res.Resources}</li>
-  </ol>
-
-  <h2>In this document</h2>
-  <ol>
-    <li><a href="#intro">Introduction</a></li>
-    <li><a href="#CreatingResources">Creating Resources</a></li>
-    <li><a href="#UsingResources">Using Resources</a>
-      <ol>
-        <li><a href="#ResourcesInCode">Using Resources in Code</a></li>
-        <li><a href="#ReferencesToResources">References to Resources</a></li>
-        <li><a href="#ReferencesToThemeAttributes">References to Theme Attributes</a></li>
-        <li><a href="#UsingSystemResources">Using System Resources</a></li>
-      </ol>
-    </li>
-    <li><a href="#AlternateResources">Alternate Resources</a></li>
-    <li><a href="#ResourcesTerminology">Terminology</a></li>
-    <li><a href="#i18n">Internationalization (I18N)</a></li>
-  </ol>
-</div>
-</div>
-
-<p>Resources are external files (that is, non-code files) that are used by
-your code and compiled into your application at build time. Android
-supports a number of different kinds of resource files, including XML,
-PNG, and JPEG files. The XML files have very different formats depending
-on what they describe. This document describes what kinds of files are
-supported, and the syntax or format of each.</p>
-<p>Resources are externalized from source code, and XML files are compiled into
-a binary, fast loading format for efficiency reasons. Strings, likewise are compressed
-into a more efficient storage form. It is for these reasons that we have these
-different resource types in the Android platform.</p>
-
-<p>This is a fairly technically dense document, and together with the
-<a href="available-resources.html">Available Resources</a>
-document, they cover a lot of information about resources. It is not necessary
-to know this document by heart to use Android, but rather to know that the
-information is here when you need it.</p>
-
-<a name="intro"></a>
-<h2>Introduction</h2>
-
-<p>This topic includes a terminology list associated with resources, and a series
-    of examples of using resources in code. For a complete guide to the supported 
-    Android resource types, see 
-    <a href="available-resources.html">Available Resources</a>.
-    </p>
-<p>The Android resource system keeps track of all non-code
-    assets associated with an application.  You use the
-    {@link android.content.res.Resources Resources} class to access your
-    application's resources; the Resources instance associated with your
-    application can generally be found through
-    {@link android.content.Context#getResources Context.getResources()}.</p>
-<p>An application's resources are compiled into the application
-binary at build time for you by the build system.  To use a resource,
-you must install it correctly in the source tree and build your
-application.  As part of the build process, symbols for each
-of the resources are generated that you can use in your source
-code -- this allows the compiler to verify that your application code matches
-up with the resources you defined.</p>
-
-<p>The rest of this section is organized as a tutorial on how to
-use resources in an application.</p>
-
-<a name="CreatingResources" id="CreatingResources"></a>
-<h2>Creating Resources</h2>
-
-<p>Android supports string, bitmap, and many other types of resource. The syntax and format
-of each, and where they're stored, depends upon the type of object. In
-general, though, you create resources from three types of files: XML files
-(everything but bitmaps and raw), bitmap files(for images) and Raw files (anything
-else, for example sound files, etc.). In fact, there are two different types of
-XML file as well, those that get compiled as-is into the package, and those that
-are used to generate resources by aapt. Here is a list of each
-resource type, the format of the file, a description of the file, and details
-of any XML files. </p>
-
-<p>You will create and store your resource files under the appropriate
-subdirectory under the <code>res/</code> directory in your project. Android
-has a resource compiler (aapt) that compiles resources according to which
-subfolder they are in, and the format of the file. Here is a list of the file
-types for each resource. See the 
-<a href="available-resources.html">Available Resources</a> for
-descriptions of each type of object, the syntax, and the format or syntax of
-the containing file.</p>
-
-<table width="100%" border="1">
-    <tr>
-        <th scope="col">Directory</th>
-        <th scope="col">Resource Types </th>
-    </tr>
-    <tr>
-        <td><code>res/anim/</code></td>
-        <td>XML files that are compiled into 
-        <a href="available-resources.html#animationdrawable">frame by
-        frame animation</a> or 
-        <a href="available-resources.html#tweenedanimation">tweened
-        animation</a> objects </td>
-    </tr>
-    <tr>
-        <td><code>res/drawable/</code></td>
-        <td><p>.png, .9.png, .jpg files that are compiled into the following
-                Drawable resource subtypes:</p>
-            <ul class="nolist">
-                <li><a href="available-resources.html#imagefileresources">bitmap files</a></li>
-                <li><a href="available-resources.html#ninepatch">9-patches (resizable bitmaps)</a></li>
-            </ul>
-            <p>To get a resource of this type, use <code>mContext.getResources().getDrawable(R.drawable.<em>imageId</em>)</code></p>
-            <p class="note"><strong>Note:</strong> Image resources placed in here 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 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
-              an image as a bit stream in order to convert it to a bitmap, put your images in the 
-              <code>res/raw/</code> folder instead, where they will not be optimized.</p>
-        </td>
-    </tr>
-    <tr>
-        <td><code>res/layout/</code></td>
-        <td>XML files that are compiled into screen layouts (or part of a screen).
-            See <a href="{@docRoot}guide/topics/ui/declaring-layout.html">Declaring Layout</a>.</td>
-    </tr>
-    <tr>
-        <td><code>res/values/</code></td>
-        <td><p>XML files that can be compiled into many kinds of resource.</p>
-            <p class="note"><strong>Note:</strong> Unlike the other res/ folders, this one
-            can hold any number of files that hold descriptions of resources to create
-            rather than the resources themselves. The XML element types control
-            where these resources are placed under the R class.</p>
-            <p>While the files can be named anything, these are
-                the typical files in this folder (the convention is to name
-                the file after the type of elements defined within):</p>
-            <ul>
-                <li><strong>arrays.xml</strong> to define arrays </li>  
-                <!-- TODO: add section on arrays -->
-                <li><strong>colors.xml</strong> to define <a href="available-resources.html#colordrawableresources">color
-                        drawables</a> and <a  href="#colorvals">color string values</a>.
-                        Use <code>Resources.getDrawable()</code> and
-                        <code>Resources.getColor(), respectively,</code>
-                to get these resources.</li>
-                <li><strong>dimens.xml</strong> to define <a href="available-resources.html#dimension">dimension value</a>. Use <code>Resources.getDimension()</code> to get
-                these resources.</li>
-                <li><strong>strings.xml</strong> to define <a href="available-resources.html#stringresources">string</a> values (use either         
-                <code>Resources.getString</code> or preferably <code>Resources.getText()</code>
-                to get
-                these resources. <code>getText()</code> will retain any rich text styling
-                which is usually desirable for UI strings.</li>
-                <li><strong>styles.xml</strong> to define <a href="available-resources.html#stylesandthemes">style</a> objects.</li>
-            </ul></td>
-    </tr>
-    <tr>
-        <td><code>res/xml/</code></td>
-        <td>Arbitrary XML files that are compiled and can be read at run time by
-            calling {@link android.content.res.Resources#getXml(int) Resources.getXML()}.</td>
-    </tr>
-    <tr>
-        <td><code>res/raw/</code></td>
-        <td>Arbitrary files to copy directly to the device. They are added uncompiled
-            to the compressed file that your application build produces. To use these
-            resources in your application, call {@link android.content.res.Resources#openRawResource(int)
-            Resources.openRawResource()} with the resource ID, which is R.raw.<em>somefilename</em>.</td>
-    </tr>
-</table>
-<p>Resources are compiled into the final APK file. Android creates a wrapper class,
-    called R, that you can use to refer to these resources in your code. R contains subclasses
-    named according to the path and file name of the source file</p>
-<a name="colorvals" id="colorvals"></a>
-<h3>Global Resource Notes</h3>
-<ul>
-    <li>Several resources allow you to define colors. Android accepts color values
-        written in various web-style formats -- a hexadecimal constant in any of the
-        following forms: #RGB, #ARGB, #RRGGBB, #AARRGGBB. </li>
-    <li>All color values support setting an alpha channel value, where the first
-        two hexadecimal numbers specify the transparency. Zero in the alpha channel
-        means transparent. The default value is opaque. </li>
-</ul>
-<a name="UsingResources" id="UsingResources"></a>
-<h2>Using Resources </h2>
-<p>This section describes how to use the resources you've created. It includes the
-    following topics:</p>
-<ul>
-    <li><a href="#ResourcesInCode">Using resources in code</a>&nbsp;- How to call
-        resources in your code to instantiate them. </li>
-    <li><a href="#ReferencesToResources">Referring to resources from other resources</a> &nbsp;-
-        You can reference resources from other resources. This lets you reuse common 
-        resource values inside resources. </li>
-    <li><a href="#AlternateResources">Supporting Alternate Resources for Alternate
-            Configurations</a> - You can specify different resources
-            to load, depending on the language or display configuration of the host
-            hardware. </li>
-</ul>
-<p>At compile time, Android generates a class named R that contains resource identifiers
-    to all the resources in your program. This class contains several subclasses,
-    one for each type of resource supported by Android, and for which you provided
-    a resource file. Each class contains one or more identifiers for the compiled resources,
-    that you use in your code to load the resource. Here is a small resource file
-    that contains string, layout (screens or parts of screens), and image resources.</p>
-<p class="note"><strong>Note:</strong> the R class is an auto-generated file and is not
-designed to be edited by hand. It will be automatically re-created as needed when
-the resources are updated.</p>
-<pre class="prettyprint">package com.android.samples;
-public final class R {
-    public static final class string {
-        public static final int greeting=0x0204000e;
-        public static final int start_button_text=0x02040001;
-        public static final int submit_button_text=0x02040008;
-        public static final int main_screen_title=0x0204000a;
-    };
-    public static final class layout {
-        public static final int start_screen=0x02070000;
-        public static final int new_user_pane=0x02070001;
-        public static final int select_user_list=0x02070002;
-
-    };
-    public static final class drawable {
-        public static final int company_logo=0x02020005;
-        public static final int smiling_cat=0x02020006;
-        public static final int yellow_fade_background=0x02020007;
-        public static final int stretch_button_1=0x02020008;
-
-    };
-};
-</pre>
-<a name="ResourcesInCode" id="ResourcesInCode"></a>
-<h3>Using Resources in Code </h3>
-
-<p>Using resources in code is just a matter of knowing the full resource ID
-and what type of object your resource has been compiled into. Here is the
-syntax for referring to a resource:</p>
-<p><code>R.<em>resource_type</em>.<em>resource_name</em></code></p>
-<p>or</p>
-<p><code>android.R.<em>resource_type</em>.<em>resource_name</em></code></p>
-
-<p>Where <code>resource_type</code> is the R subclass that holds a specific type
-of resource. <code>resource_name</code> is the <em>name</em> attribute for resources
-defined in XML files, or the file name (without the extension) for resources
-defined by other file types. Each type of resource will be added to a specific
-R subclass, depending on the type of resource it is; to learn which R subclass
-hosts your compiled resource type, consult the 
-<a href="available-resources.html">Available Resources</a> document. Resources compiled by your own application can
-be referred to without a package name (simply as
-<code>R.<em>resource_type</em>.<em>resource_name</em></code>). Android contains
-a number of standard resources, such as screen styles and button backgrounds. To
-refer to these in code, you must qualify them with <code>android</code>, as in
-<code>android.R.drawable.button_background</code>.</p>
-
-<p>Here are some good and bad examples of using compiled resources in code:</p>
-
-<pre class="prettyprint">// Load a background for the current screen from a drawable resource.
-this.getWindow().setBackgroundDrawableResource(R.drawable.my_background_image);
-
-// WRONG Sending a string resource reference into a 
-// method that expects a string.
-this.getWindow().setTitle(R.string.main_title);
-
-// RIGHT Need to get the title from the Resources wrapper.
-this.getWindow().setTitle(Resources.getText(R.string.main_title));
-
-// Load a custom layout for the current screen.
-setContentView(R.layout.main_screen);
-
-// Set a slide in animation for a ViewFlipper object.
-mFlipper.setInAnimation(AnimationUtils.loadAnimation(this, 
-        R.anim.hyperspace_in));
-
-// Set the text on a TextView object.
-TextView msgTextView = (TextView)findViewByID(R.id.msg);
-msgTextView.setText(R.string.hello_message); </pre>
-
-<a name="ReferencesToResources" id="ReferencesToResources"></a>
-<h3>References to Resources</h3>
-
-<p>A value supplied in an attribute (or resource) can also be a reference to
-a resource.  This is often used in layout files to supply strings (so they
-can be localized) and images (which exist in another file), though a reference
-can be any resource type including colors and integers.</p>
-
-<p>For example, if we have 
-<a href="available-resources.html#colordrawableresources">color 
-resources</a>, we can write a layout file that sets the text color size to be
-the value contained in one of those resources:</p>
-
-<pre>
-&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
-&lt;EditText id=&quot;text&quot;
-    xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
-    android:layout_width=&quot;fill_parent&quot; android:layout_height=&quot;fill_parent&quot;
-    <strong>android:textColor=&quot;&#64;color/opaque_red&quot;</strong>
-    android:text=&quot;Hello, World!&quot; /&gt;
-</pre>
-
-<p>Note here the use of the '@' prefix to introduce a resource reference -- the
-text following that is the name of a resource in the form
-of <code>@[package:]type/name</code>.  In this case we didn't need to specify
-the package because we are referencing a resource in our own package.  To
-reference a system resource, you would need to write:</p>
-
-<pre>
-&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
-&lt;EditText id=&quot;text&quot;
-    xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
-    android:layout_width=&quot;fill_parent&quot; android:layout_height=&quot;fill_parent&quot;
-    android:textColor=&quot;&#64;<strong>android:</strong>color/opaque_red&quot;
-    android:text=&quot;Hello, World!&quot; /&gt;
-</pre>
-
-<p>As another example, you should always use resource references when supplying
-strings in a layout file so that they can be localized:</p>
-
-<pre>
-&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
-&lt;EditText id=&quot;text&quot;
-    xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
-    android:layout_width=&quot;fill_parent&quot; android:layout_height=&quot;fill_parent&quot;
-    android:textColor=&quot;&#64;android:color/opaque_red&quot;
-    android:text=&quot;&#64;string/hello_world&quot; /&gt;
-</pre>
-
-<p>This facility can also be used to create references between resources.
-For example, we can create new drawable resources that are aliases for
-existing images:</p>
-
-<pre>
-&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
-&lt;resources&gt;
-    &lt;drawable id=&quot;my_background&quot;&gt;&#64;android:drawable/theme2_background&lt;/drawable&gt;
-&lt;/resources&gt;
-</pre>
-
-<a name="ReferencesToThemeAttributes"></a>
-<h3>References to Theme Attributes</h3>
-
-<p>Another kind of resource value allows you to reference the value of an
-attribute in the current theme.  This attribute reference can <em>only</em>
-be used in style resources and XML attributes; it allows you to customize the
-look of UI elements by changing them to standard variations supplied by the
-current theme, instead of supplying more concrete values.</p>
-
-<p>As an example, we can use this in our layout to set the text color to
-one of the standard colors defined in the base system theme:</p>
-
-<pre>
-&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
-&lt;EditText id=&quot;text&quot;
-    xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
-    android:layout_width=&quot;fill_parent&quot; android:layout_height=&quot;fill_parent&quot;
-    <strong>android:textColor=&quot;?android:textDisabledColor&quot;</strong>
-    android:text=&quot;&#64;string/hello_world&quot; /&gt;
-</pre>
-
-<p>Note that this is very similar to a resource reference, except we are using
-an '?' prefix instead of '@'.  When you use this markup, you are supplying
-the name of an attribute resource that will be looked up in the theme --
-because the resource tool knows that an attribute resource is expected,
-you do not need to explicitly state the type (which would be
-<code>?android:attr/android:textDisabledColor</code>).</p>
-
-<p>Other than using this resource identifier to find the value in the
-theme instead of raw resources, the name syntax is identical to the '@' format:
-<code>?[namespace:]type/name</code> with the type here being optional.</p>
-
-<a name="UsingSystemResources"></a>
-<h3>Using System Resources</h3>
-
-<p>Many resources included with the system are available to applications.
-All such resources are defined under the class "android.R".  For example,
-you can display the standard application icon in a screen with the following
-code:</p>
-
-<pre class="prettyprint">
-public class MyActivity extends Activity
-{
-    public void onStart() 
-    {
-        requestScreenFeatures(FEATURE_BADGE_IMAGE);
-
-        super.onStart();
-
-        setBadgeResource(android.R.drawable.sym_def_app_icon);
-    }
-}
-</pre>
-
-<p>In a similar way, this code will apply to your screen the standard
-"green background" visual treatment defined by the system:</p>
-
-<pre class="prettyprint">
-public class MyActivity extends Activity
-{
-    public void onStart() 
-    {
-        super.onStart();
-
-        setTheme(android.R.style.Theme_Black);
-    }
-}
-</pre>
-
-<a name="AlternateResources" id="AlternateResources"></a>
-<h2>Alternate Resources (for alternate languages and configurations)</h2>
-
-<p>You can supply different resources for your product according to the UI
-language or hardware configuration on the device. Note that although you can
-include different string, layout, and other resources, the SDK does not expose
-methods to let you specify which alternate resource set to load. Android
-detects the proper set for the hardware and location, and loads them as
-appropriate. Users can select alternate language settings using the settings
-panel on the device. </p>
-<p>To include alternate resources, create parallel resource folders with
-qualifiers appended to the folder names, indicating the configuration it
-applies to (language, screen orientation, and so on). For example, here is a
-project that holds one string resource file for English, and another for
-French:</p>
-
-<pre>
-MyApp/
-    res/
-        values-en/
-            strings.xml
-        values-fr/
-            strings.xml
-</pre>
-
-<p>Android supports several types of qualifiers, with various values for each.
-Append these to the end of the resource folder name, separated by dashes. You
-can add multiple qualifiers to each folder name, but they must appear in the
-order they are listed here. For example, a folder containing drawable
-resources for a fully specified configuration would look like:</p>
-
-<pre>
-MyApp/
-    res/
-        drawable-en-rUS-port-160dpi-finger-keysexposed-qwerty-dpad-480x320/
-</pre>
-
-<p>More typically, you will only specify a few specific configuration options
-that a resource is defined for. You may drop any of the values from the
-complete list, as long as the remaining values are still in the same
-order:</p>
-
-<pre>
-MyApp/
-    res/
-        drawable-en-rUS-finger/
-        drawable-port/
-        drawable-port-160dpi/
-        drawable-qwerty/
-</pre>
-
-<table border="1">
-    <tr>
-        <th> Qualifier </th>
-        <th> Values </th>
-    </tr>
-    <tr>
-        <td>Language</td>
-        <td>The two letter <a href="http://www.loc.gov/standards/iso639-2/php/code_list.php">ISO
-                639-1</a> language code in lowercase. For example: 
-                <code>en</code>, <code>fr</code>, <code>es</code> </td>
-    </tr>
-    <tr>
-        <td>Region</td>
-        <td>The two letter
-        <a href="http://www.iso.org/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html">ISO
-                3166-1-alpha-2</a> language code in uppercase preceded by a lowercase
-            &quot;r&quot;. For example: <code>rUS</code>, <code>rFR</code>, <code>rES</code></td>
-    </tr>
-    <tr>
-        <td>Screen orientation</td>
-        <td><code>port</code>, <code>land</code>, <code>square</code> </td>
-    </tr>
-    <tr>
-        <td>Screen pixel density</td>
-        <td><code>92dpi</code>, <code>108dpi</code>, etc. </td>
-    </tr>
-    <tr>
-        <td>Touchscreen type</td>
-        <td><code>notouch</code>, <code>stylus</code>, <code>finger</code></td>
-    </tr>
-    <tr>
-        <td>Whether the keyboard is available to the user</td>
-        <td><code>keysexposed</code>, <code>keyshidden</code> </td>
-    </tr>
-    <tr>
-        <td>Primary text input method</td>
-        <td><code>nokeys</code>, <code>qwerty</code>, <code>12key</code> </td>
-    </tr>
-    <tr>
-        <td>Primary non-touchscreen<br />
-            navigation method</td>
-        <td><code>nonav</code>, <code>dpad</code>, <code>trackball</code>, <code>wheel</code> </td>
-    </tr>
-    <tr>
-        <td>Screen dimensions</td>
-        <td><code>320x240</code>, <code>640x480</code>, etc. The larger dimension
-            must be specified first. </td>
-    </tr>
-</table>
-
-<p>This list does not include device-specific parameters such as carrier,
-branding, device/hardware, or manufacturer. Everything that an application
-needs to know about the device that it is running on is encoded via the
-resource qualifiers in the table above.</p>
-
-<p>Here are some general guidelines on qualified resource directory names:</p>
-
-<ul>
-    <li>Values are separated by a dash (as well as a dash after the base directory
-        name) </li>
-    <li>Values are case-sensitive (even though they must be unique across all folder
-        names in a case-insensitive way)<br />For example,</li>
-    <ul>
-        <li>A portrait-specific <code>drawable</code> directory must be named
-            <code>drawable-port</code>, not <code>drawable-PORT</code>.</li>
-        <li>You may not have two directories named <code>drawable-port</code>
-            and <code>drawable-PORT</code>, even if you had intended "port" and
-            "PORT" to refer to different parameter values.</li>
-    </ul>
-    <li>Only one value for each qualifier type is supported (that is, you cannot
-        specify <code>drawable-rEN-rFR/</code>)</li>
-    <li>You can specify multiple parameters to define specific configurations,
-        but they must always be in the order listed above.
-        For example, <code>drawable-en-rUS-land</code> will apply to landscape view,
-        US-English devices. </li>
-    <li>Android will try to find the most specific matching directory for the current
-        configuration, as described below</li>
-    <li>The order of parameters listed in this table is used to break a tie in case
-        of multiple qualified directories (see the example given below) </li>
-    <li>All directories, both qualified and unqualified, live under the <code>res/</code> folder.
-        Qualified directories cannot be nested (you cannot have <code>res/drawable/drawable-en</code>) </li>
-    <li>All resources will be referenced in code or resource reference syntax by
-        their simple, undecorated name. So if a resource is named this:<br />
-        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<code>MyApp/res/drawable-port-92dp/myimage.png</code><br />
-        It would be referenced as this:<br />
-        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<code>R.drawable.myimage</code> (code)<br />
-        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<code>&#064;drawable/myimage</code> (XML)</li>
-</ul>
-
-<h3>How Android finds the best matching directory </h3>
-
-<p>Android will pick which of the various underlying resource files should be
-used at runtime, depending on the current configuration. The selection process
-is as follows:</p>
-
-<ol>
-    <li>
-            Eliminate any resources whose configuration does not match the current
-            device configuration. For example, if the screen pixel density is 108dpi,
-            this would eliminate only <code>MyApp/res/drawable-port-92dpi/</code>.
-        <blockquote>
-            <pre>
-MyApp/res/drawable/myimage.png
-MyApp/res/drawable-en/myimage.png
-MyApp/res/drawable-port/myimage.png
-<strike>MyApp/res/drawable-port-92dpi/myimage.png</strike>
-</pre>
-        </blockquote>
-    </li>
-    <li>
-            Pick the resources with the highest number of matching configurations.
-            For example, if our locale is en-GB and orientation is port, then we
-            have two candidates with one matching configuration each: 
-            <code>MyApp/res/drawable-en/</code> and <code>MyApp/res/drawable-port/</code>.
-            The directory <code>MyApp/res/drawable/</code> is eliminated because
-            it has zero matching configurations, while the others have one matching
-            configuration.
-        <blockquote>
-            <pre>
-<strike>MyApp/res/drawable/myimage.png</strike>
-MyApp/res/drawable-en/myimage.png
-MyApp/res/drawable-port/myimage.png
-</pre>
-        </blockquote>
-    </li>
-    <li>
-            Pick the final matching file based on configuration precedence, which
-            is the order of parameters listed in the table above. That is, it is
-            more important to match the language than the orientation, so we break
-            the tie by picking the language-specific file, <code>MyApp/res/drawable-en/</code>.
-        <blockquote>
-            <pre>MyApp/res/drawable-en/myimage.png
-<strike>MyApp/res/drawable-port/myimage.png</strike>
-</pre>
-        </blockquote>
-    </li>
-</ol>
-
-<a name="ResourcesTerminology"></a>
-<h2>Terminology</h2>
-
-<p>The resource system brings a number of different pieces together to
-form the final complete resource functionality.  To help understand the
-overall system, here are some brief definitions of the core concepts and
-components you will encounter in using it:</p>
-
-<p><strong>Asset</strong>: A single blob of data associated with an application. This
-includes object files compiled from the Java source code, graphics (such as PNG
-images), XML files, etc. These files are organized in a directory hierarchy
-that, during final packaging of the application, is bundled together into a
-single ZIP file.</p>
-
-<p><strong>aapt</strong>: Android Asset Packaging Tool. The tool that generates the 
-final ZIP file of application assets.  In addition to collecting raw assets 
-together, it also parses resource definitions into binary asset data.</p>
-
-<p><strong>Resource Table</strong>: A special asset that aapt generates for you,
-describing all of the resources contained in an application/package.
-This file is accessed for you by the Resources class; it is not touched
-directly by applications.</p>
-
-<p><strong>Resource</strong>: An entry in the Resource Table describing a single
-named value.  Broadly, there are two types of resources: primitives and
-bags.</p>
-
-<p><strong>Resource Identifier</strong>: In the Resource Table all resources are
-identified by a unique integer number.  In source code (resource descriptions,
-XML files, Java source code) you can use symbolic names that stand as constants for
-the actual resource identifier integer.</p>
-
-<p><strong>Primitive Resource</strong>: All primitive resources can be written as a
-simple string, using formatting to describe a variety of primitive types
-included in the resource system: integers, colors, strings, references to
-other resources, etc.  Complex resources, such as bitmaps and XML
-describes, are stored as a primitive string resource whose value is the path
-of the underlying Asset holding its actual data.</p>
-
-<p><strong>Bag Resource</strong>: A special kind of resource entry that, instead of a
-simple string, holds an arbitrary list of name/value pairs.  Each name is
-itself a resource identifier, and each value can hold
-the same kinds of string formatted data as a normal resource.  Bags also
-support inheritance: a bag can inherit the values from another bag, selectively
-replacing or extending them to generate its own contents.</p>
-
-<p><strong>Kind</strong>: The resource kind is a way to organize resource identifiers
-for various purposes.  For example, drawable resources are used to
-instantiate Drawable objects, so their data is a primitive resource containing
-either a color constant or string path to a bitmap or XML asset.  Other
-common resource kinds are string (localized string primitives), color
-(color primitives), layout (a string path to an XML asset describing a view
-layout), and style (a bag resource describing user interface attributes).
-There is also a standard "attr" resource kind, which defines the resource
-identifiers to be used for naming bag items and XML attributes</p>
-
-<p><strong>Style</strong>: The name of the resource kind containing bags that are used
-to supply a set of user interface attributes.  For example, a TextView class may
-be given a style resource that defines its text size, color, and alignment.
-In a layout XML file, you associate a style with a bag using the "style"
-attribute, whose value is the name of the style resource.</p>
-
-<p><strong>Style Class</strong>: Specifies a related set of attribute resources.
-This data is not placed in the resource table itself, but used to generate
-constants in the source code that make it easier for you to retrieve values out of
-a style resource and/or XML tag's attributes.  For example, the
-Android platform defines a "View" style class that
-contains all of the standard view attributes: padding, visibility,
-background, etc.; when View is inflated it uses this style class to
-retrieve those values from the XML file (at which point style and theme
-information is applied as approriate) and load them into its instance.</p>
-
-<p><strong>Configuration</strong>: For any particular resource identifier, there may be
-multiple different available values depending on the current configuration.
-The configuration includes the locale (language and country), screen
-orientation, screen density, etc.  The current configuration is used to
-select which resource values are in effect when the resource table is
-loaded.</p>
-
-<p><strong>Theme</strong>: A standard style resource that supplies global
-attribute values for a particular context.  For example, when writing an
-Activity the application developer can select a standard theme to use, such
-as the Theme.White or Theme.Black styles; this style supplies information
-such as the screen background image/color, default text color, button style,
-text editor style, text size, etc.  When inflating a layout resource, most
-values for widgets (the text color, selector, background) if not explicitly
-set will come from the current theme; style and attribute
-values supplied in the layout can also assign their value from explicitly
-named values in the theme attributes if desired.</p>
-
-<p><strong>Overlay</strong>: A resource table that does not define a new set of resources,
-but instead replaces the values of resources that are in another resource table.
-Like a configuration, this is applied at load time
-to the resource data; it can add new configuration values (for example
-strings in a new locale), replace existing values (for example change
-the standard white background image to a "Hello Kitty" background image),
-and modify resource bags (for example change the font size of the Theme.White
-style to have an 18 pt font size).  This is the facility that allows the
-user to select between different global appearances of their device, or
-download files with new appearances.</p>
-
-<h2>Resource Reference</h2>
-<p>The <a href="available-resources.html">Available Resources</a>
-document provides a detailed list of the various types of resource and how to use them
-from within the Java source code, or from other references.</p>
-
-<a name="i18n" id="i18n"></a>
-<h2>Internationalization and Localization</h2>
-<p class="note"><strong>Coming Soon:</strong> Internationalization and Localization are
-critical, but are also not quite ready yet in the current SDK. As the
-SDK matures, this section will contain information on the Internationalization
-and Localization features of the Android platform. In the meantime, it is a good
-idea to start by externalizing all strings, and practicing good structure in
-creating and using resources.</p>
-
+page.title=Resources and Internationalization

+parent.title=Resources and Assets

+parent.link=index.html

+@jd:body

+

+<div id="qv-wrapper">

+<div id="qv">

+

+  <h2>Key classes</h2>

+  <ol>

+    <li>{@link android.content.res.Resources}</li>

+  </ol>

+

+  <h2>In this document</h2>

+  <ol>

+    <li><a href="#intro">Introduction</a></li>

+    <li><a href="#CreatingResources">Creating Resources</a></li>

+    <li><a href="#UsingResources">Using Resources</a>

+      <ol>

+        <li><a href="#ResourcesInCode">Using Resources in Code</a></li>

+        <li><a href="#ReferencesToResources">References to Resources</a></li>

+        <li><a href="#ReferencesToThemeAttributes">References to Theme Attributes</a></li>

+        <li><a href="#UsingSystemResources">Using System Resources</a></li>

+      </ol>

+    </li>

+    <li><a href="#AlternateResources">Alternate Resources</a></li>

+    <li><a href="#ResourcesTerminology">Terminology</a></li>

+    <li><a href="#i18n">Internationalization (I18N)</a></li>

+  </ol>

+</div>

+</div>

+

+<p>Resources are external files (that is, non-code files) that are used by

+your code and compiled into your application at build time. Android

+supports a number of different kinds of resource files, including XML,

+PNG, and JPEG files. The XML files have very different formats depending

+on what they describe. This document describes what kinds of files are

+supported, and the syntax or format of each.</p>

+<p>Resources are externalized from source code, and XML files are compiled into

+a binary, fast loading format for efficiency reasons. Strings, likewise, are compressed

+into a more efficient storage form. It is for these reasons that we have these

+different resource types in the Android platform.</p>

+

+<p>This is a fairly technically dense document, and together with the

+<a href="available-resources.html">Available Resources</a>

+document, they cover a lot of information about resources. It is not necessary

+to know this document by heart to use Android, but rather to know that the

+information is here when you need it.</p>

+

+<a name="intro"></a>

+<h2>Introduction</h2>

+

+<p>This topic includes a terminology list associated with resources, and a series

+    of examples of using resources in code. For a complete guide to the supported 

+    Android resource types, see 

+    <a href="available-resources.html">Available Resources</a>.

+    </p>

+<p>The Android resource system keeps track of all non-code

+    assets associated with an application.  You use the

+    {@link android.content.res.Resources Resources} class to access your

+    application's resources; the Resources instance associated with your

+    application can generally be found through

+    {@link android.content.Context#getResources Context.getResources()}.</p>

+<p>An application's resources are compiled into the application

+binary at build time for you by the build system.  To use a resource,

+you must install it correctly in the source tree and build your

+application.  As part of the build process, symbols for each

+of the resources are generated that you can use in your source

+code -- this allows the compiler to verify that your application code matches

+up with the resources you defined.</p>

+

+<p>The rest of this section is organized as a tutorial on how to

+use resources in an application.</p>

+

+<a name="CreatingResources" id="CreatingResources"></a>

+<h2>Creating Resources</h2>

+

+<p>Android supports string, bitmap, and many other types of resource. The syntax and format

+of each, and where they're stored, depends upon the type of object. In

+general, though, you create resources from three types of files: XML files

+(everything but bitmaps and raw), bitmap files(for images) and Raw files (anything

+else, for example sound files, etc.). In fact, there are two different types of

+XML file as well, those that get compiled as-is into the package, and those that

+are used to generate resources by aapt. Here is a list of each

+resource type, the format of the file, a description of the file, and details

+of any XML files. </p>

+

+<p>You will create and store your resource files under the appropriate

+subdirectory under the <code>res/</code> directory in your project. Android

+has a resource compiler (aapt) that compiles resources according to which

+subfolder they are in, and the format of the file. Table 1 shows a llist of the file

+types for each resource. See the 

+<a href="available-resources.html">Available Resources</a> for

+descriptions of each type of object, the syntax, and the format or syntax of

+the containing file.</p>

+<p class="caption">Table 1</p>

+<table width="100%" border="1">

+    <tr>

+        <th scope="col">Directory</th>

+        <th scope="col">Resource Types </th>

+    </tr>

+    <tr>

+        <td><code>res/anim/</code></td>

+        <td>XML files that are compiled into 

+        <a href="available-resources.html#animationdrawable">frame by

+        frame animation</a> or 

+        <a href="available-resources.html#tweenedanimation">tweened

+        animation</a> objects </td>

+    </tr>

+    <tr>

+        <td><code>res/drawable/</code></td>

+        <td><p>.png, .9.png, .jpg files that are compiled into the following

+                Drawable resource subtypes:</p>

+            <ul class="nolist">

+                <li><a href="available-resources.html#imagefileresources">bitmap files</a></li>

+                <li><a href="available-resources.html#ninepatch">9-patches (resizable bitmaps)</a></li>

+            </ul>

+            <p>To get a resource of this type, use <code>mContext.getResources().getDrawable(R.drawable.<em>imageId</em>)</code></p>

+            <p class="note"><strong>Note:</strong> Image resources placed in here 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 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

+              an image as a bit stream in order to convert it to a bitmap, put your images in the 

+              <code>res/raw/</code> folder instead, where they will not be optimized.</p>

+        </td>

+    </tr>

+    <tr>

+        <td><code>res/layout/</code></td>

+        <td>XML files that are compiled into screen layouts (or part of a screen).

+            See <a href="{@docRoot}guide/topics/ui/declaring-layout.html">Declaring Layout</a>.</td>

+    </tr>

+    <tr>

+        <td><code>res/values/</code></td>

+        <td><p>XML files that can be compiled into many kinds of resource.</p>

+            <p class="note"><strong>Note:</strong> Unlike the other res/ folders, this one

+            can hold any number of files that hold descriptions of resources to create

+            rather than the resources themselves. The XML element types control

+            where these resources are placed under the R class.</p>

+            <p>While the files can be named anything, these are

+                the typical files in this folder (the convention is to name

+                the file after the type of elements defined within):</p>

+            <ul>

+                <li><strong>arrays.xml</strong> to define arrays </li>  

+                <!-- TODO: add section on arrays -->

+                <li><strong>colors.xml</strong> to define <a href="available-resources.html#colordrawableresources">color

+                        drawables</a> and <a  href="#colorvals">color string values</a>.

+                        Use <code>Resources.getDrawable()</code> and

+                        <code>Resources.getColor(), respectively,</code>

+                to get these resources.</li>

+                <li><strong>dimens.xml</strong> to define <a href="available-resources.html#dimension">dimension value</a>. Use <code>Resources.getDimension()</code> to get

+                these resources.</li>

+                <li><strong>strings.xml</strong> to define <a href="available-resources.html#stringresources">string</a> values (use either         

+                <code>Resources.getString</code> or preferably <code>Resources.getText()</code>

+                to get

+                these resources. <code>getText()</code> will retain any rich text styling

+                which is usually desirable for UI strings.</li>

+                <li><strong>styles.xml</strong> to define <a href="available-resources.html#stylesandthemes">style</a> objects.</li>

+            </ul></td>

+    </tr>

+    <tr>

+        <td><code>res/xml/</code></td>

+        <td>Arbitrary XML files that are compiled and can be read at run time by

+            calling {@link android.content.res.Resources#getXml(int) Resources.getXML()}.</td>

+    </tr>

+    <tr>

+        <td><code>res/raw/</code></td>

+        <td>Arbitrary files to copy directly to the device. They are added uncompiled

+            to the compressed file that your application build produces. To use these

+            resources in your application, call {@link android.content.res.Resources#openRawResource(int)

+            Resources.openRawResource()} with the resource ID, which is R.raw.<em>somefilename</em>.</td>

+    </tr>

+</table>

+<p>Resources are compiled into the final APK file. Android creates a wrapper class,

+    called R, that you can use to refer to these resources in your code. R contains subclasses

+    named according to the path and file name of the source file</p>

+<a name="colorvals" id="colorvals"></a>

+<h3>Global Resource Notes</h3>

+<ul>

+    <li>Several resources allow you to define colors. Android accepts color values

+        written in various web-style formats -- a hexadecimal constant in any of the

+        following forms: #RGB, #ARGB, #RRGGBB, #AARRGGBB. </li>

+    <li>All color values support setting an alpha channel value, where the first

+        two hexadecimal numbers specify the transparency. Zero in the alpha channel

+        means transparent. The default value is opaque. </li>

+</ul>

+<a name="UsingResources" id="UsingResources"></a>

+<h2>Using Resources </h2>

+<p>This section describes how to use the resources you've created. It includes the

+    following topics:</p>

+<ul>

+    <li><a href="#ResourcesInCode">Using resources in code</a>&nbsp;- How to call

+        resources in your code to instantiate them. </li>

+    <li><a href="#ReferencesToResources">Referring to resources from other resources</a> &nbsp;-

+        You can reference resources from other resources. This lets you reuse common 

+        resource values inside resources. </li>

+    <li><a href="#AlternateResources">Supporting Alternate Resources for Alternate

+            Configurations</a> - You can specify different resources

+            to load, depending on the language or display configuration of the host

+            hardware. </li>

+</ul>

+<p>At compile time, Android generates a class named R that contains resource identifiers

+    to all the resources in your program. This class contains several subclasses,

+    one for each type of resource supported by Android, and for which you provided

+    a resource file. Each class contains one or more identifiers for the compiled resources,

+    that you use in your code to load the resource. Here is a small resource file

+    that contains string, layout (screens or parts of screens), and image resources.</p>

+<p class="note"><strong>Note:</strong> the R class is an auto-generated file and is not

+designed to be edited by hand. It will be automatically re-created as needed when

+the resources are updated.</p>

+<pre class="prettyprint">package com.android.samples;

+public final class R {

+    public static final class string {

+        public static final int greeting=0x0204000e;

+        public static final int start_button_text=0x02040001;

+        public static final int submit_button_text=0x02040008;

+        public static final int main_screen_title=0x0204000a;

+    };

+    public static final class layout {

+        public static final int start_screen=0x02070000;

+        public static final int new_user_pane=0x02070001;

+        public static final int select_user_list=0x02070002;

+

+    };

+    public static final class drawable {

+        public static final int company_logo=0x02020005;

+        public static final int smiling_cat=0x02020006;

+        public static final int yellow_fade_background=0x02020007;

+        public static final int stretch_button_1=0x02020008;

+

+    };

+};

+</pre>

+<a name="ResourcesInCode" id="ResourcesInCode"></a>

+<h3>Using Resources in Code </h3>

+

+<p>Using resources in code is just a matter of knowing the full resource ID

+and what type of object your resource has been compiled into. Here is the

+syntax for referring to a resource:</p>

+<p><code>R.<em>resource_type</em>.<em>resource_name</em></code></p>

+<p>or</p>

+<p><code>android.R.<em>resource_type</em>.<em>resource_name</em></code></p>

+

+<p>Where <code>resource_type</code> is the R subclass that holds a specific type

+of resource. <code>resource_name</code> is the <em>name</em> attribute for resources

+defined in XML files, or the file name (without the extension) for resources

+defined by other file types. Each type of resource will be added to a specific

+R subclass, depending on the type of resource it is; to learn which R subclass

+hosts your compiled resource type, consult the 

+<a href="available-resources.html">Available Resources</a> document. Resources compiled by your own application can

+be referred to without a package name (simply as

+<code>R.<em>resource_type</em>.<em>resource_name</em></code>). Android contains

+a number of standard resources, such as screen styles and button backgrounds. To

+refer to these in code, you must qualify them with <code>android</code>, as in

+<code>android.R.drawable.button_background</code>.</p>

+

+<p>Here are some good and bad examples of using compiled resources in code:</p>

+

+<pre class="prettyprint">// Load a background for the current screen from a drawable resource.

+this.getWindow().setBackgroundDrawableResource(R.drawable.my_background_image);

+

+// WRONG Sending a string resource reference into a 

+// method that expects a string.

+this.getWindow().setTitle(R.string.main_title);

+

+// RIGHT Need to get the title from the Resources wrapper.

+this.getWindow().setTitle(Resources.getText(R.string.main_title));

+

+// Load a custom layout for the current screen.

+setContentView(R.layout.main_screen);

+

+// Set a slide in animation for a ViewFlipper object.

+mFlipper.setInAnimation(AnimationUtils.loadAnimation(this, 

+        R.anim.hyperspace_in));

+

+// Set the text on a TextView object.

+TextView msgTextView = (TextView)findViewByID(R.id.msg);

+msgTextView.setText(R.string.hello_message); </pre>

+

+<a name="ReferencesToResources" id="ReferencesToResources"></a>

+<h3>References to Resources</h3>

+

+<p>A value supplied in an attribute (or resource) can also be a reference to

+a resource.  This is often used in layout files to supply strings (so they

+can be localized) and images (which exist in another file), though a reference

+can be any resource type including colors and integers.</p>

+

+<p>For example, if we have 

+<a href="available-resources.html#colordrawableresources">color 

+resources</a>, we can write a layout file that sets the text color size to be

+the value contained in one of those resources:</p>

+

+<pre>

+&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;

+&lt;EditText id=&quot;text&quot;

+    xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;

+    android:layout_width=&quot;fill_parent&quot; android:layout_height=&quot;fill_parent&quot;

+    <strong>android:textColor=&quot;&#64;color/opaque_red&quot;</strong>

+    android:text=&quot;Hello, World!&quot; /&gt;

+</pre>

+

+<p>Note here the use of the '@' prefix to introduce a resource reference -- the

+text following that is the name of a resource in the form

+of <code>@[package:]type/name</code>.  In this case we didn't need to specify

+the package because we are referencing a resource in our own package.  To

+reference a system resource, you would need to write:</p>

+

+<pre>

+&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;

+&lt;EditText id=&quot;text&quot;

+    xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;

+    android:layout_width=&quot;fill_parent&quot; android:layout_height=&quot;fill_parent&quot;

+    android:textColor=&quot;&#64;<strong>android:</strong>color/opaque_red&quot;

+    android:text=&quot;Hello, World!&quot; /&gt;

+</pre>

+

+<p>As another example, you should always use resource references when supplying

+strings in a layout file so that they can be localized:</p>

+

+<pre>

+&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;

+&lt;EditText id=&quot;text&quot;

+    xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;

+    android:layout_width=&quot;fill_parent&quot; android:layout_height=&quot;fill_parent&quot;

+    android:textColor=&quot;&#64;android:color/opaque_red&quot;

+    android:text=&quot;&#64;string/hello_world&quot; /&gt;

+</pre>

+

+<p>This facility can also be used to create references between resources.

+For example, we can create new drawable resources that are aliases for

+existing images:</p>

+

+<pre>

+&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;

+&lt;resources&gt;

+    &lt;drawable id=&quot;my_background&quot;&gt;&#64;android:drawable/theme2_background&lt;/drawable&gt;

+&lt;/resources&gt;

+</pre>

+

+<a name="ReferencesToThemeAttributes"></a>

+<h3>References to Theme Attributes</h3>

+

+<p>Another kind of resource value allows you to reference the value of an

+attribute in the current theme.  This attribute reference can <em>only</em>

+be used in style resources and XML attributes; it allows you to customize the

+look of UI elements by changing them to standard variations supplied by the

+current theme, instead of supplying more concrete values.</p>

+

+<p>As an example, we can use this in our layout to set the text color to

+one of the standard colors defined in the base system theme:</p>

+

+<pre>

+&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;

+&lt;EditText id=&quot;text&quot;

+    xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;

+    android:layout_width=&quot;fill_parent&quot; android:layout_height=&quot;fill_parent&quot;

+    <strong>android:textColor=&quot;?android:textDisabledColor&quot;</strong>

+    android:text=&quot;&#64;string/hello_world&quot; /&gt;

+</pre>

+

+<p>Note that this is very similar to a resource reference, except we are using

+an '?' prefix instead of '@'.  When you use this markup, you are supplying

+the name of an attribute resource that will be looked up in the theme --

+because the resource tool knows that an attribute resource is expected,

+you do not need to explicitly state the type (which would be

+<code>?android:attr/android:textDisabledColor</code>).</p>

+

+<p>Other than using this resource identifier to find the value in the

+theme instead of raw resources, the name syntax is identical to the '@' format:

+<code>?[namespace:]type/name</code> with the type here being optional.</p>

+

+<a name="UsingSystemResources"></a>

+<h3>Using System Resources</h3>

+

+<p>Many resources included with the system are available to applications.

+All such resources are defined under the class "android.R".  For example,

+you can display the standard application icon in a screen with the following

+code:</p>

+

+<pre class="prettyprint">

+public class MyActivity extends Activity

+{

+    public void onStart() 

+    {

+        requestScreenFeatures(FEATURE_BADGE_IMAGE);

+

+        super.onStart();

+

+        setBadgeResource(android.R.drawable.sym_def_app_icon);

+    }

+}

+</pre>

+

+<p>In a similar way, this code will apply to your screen the standard

+"green background" visual treatment defined by the system:</p>

+

+<pre class="prettyprint">

+public class MyActivity extends Activity

+{

+    public void onStart() 

+    {

+        super.onStart();

+

+        setTheme(android.R.style.Theme_Black);

+    }

+}

+</pre>

+

+<a name="AlternateResources" id="AlternateResources"></a>

+<h2>Alternate Resources (for alternate languages and configurations)</h2>

+

+<p>You can supply different resources for your application to use depending on the UI

+language or hardware configuration on the device. Note that although you can

+include different string, layout, and other resources, the SDK does not expose

+methods to let you specify which alternate resource set to load. Android

+detects the proper set for the hardware and location, and loads them as

+appropriate. Users can select alternate language settings using the settings

+panel on the device. </p>

+<p>To include alternate resources, create parallel resource folders with

+qualifiers appended to the folder names, indicating the configuration it

+applies to (language, screen orientation, and so on). For example, here is a

+project that holds one string resource file for English, and another for

+French:</p>

+

+<pre>

+MyApp/

+    res/

+        values-en/

+            strings.xml

+        values-fr/

+            strings.xml

+</pre>

+

+<p>Android supports several types of qualifiers, with various values for each.

+Append these to the end of the resource folder name, separated by dashes. You

+can add multiple qualifiers to each folder name, but they must appear in the

+order they are listed here. For example, a folder containing drawable

+resources for a fully specified configuration would look like this:</p>

+

+<pre>

+MyApp/

+    res/

+        drawable-en-rUS-port-160dpi-finger-keysexposed-qwerty-dpad-480x320/

+</pre>

+

+<p>More typically, you will only specify a few specific configuration options. You may drop any of the values from the

+complete list, as long as the remaining values are still in the same

+order:</p>

+

+<pre>

+MyApp/

+    res/

+        drawable-en-rUS-finger/

+        drawable-port/

+        drawable-port-160dpi/

+        drawable-qwerty/

+</pre>

+<p>Table 2 lists the valid folder-name qualifiers, in order of precedence. Qualifiers that are listed higher in the table take precedence over those listed lower, as described in <a href="#best-match">How Android finds the best matching directory</a>. </p>

+<p class="caption" id="table2">Table 2</p>

+<table border="1">

+    <tr>

+        <th> Qualifier </th>

+        <th> Values </th>

+    </tr>

+    <tr>

+      <td>MCC and MNC</td>

+      <td>The <a href="http://en.wikipedia.org/wiki/Mobile_country_code">mobile country code</a> and <a href="http://en.wikipedia.org/wiki/Mobile_Network_Code">mobile network code</a> from the SIM in the device. For example  <code>mcc310-mnc004</code> (U.S., Verizon brand); <code>mcc208-mnc00</code> (France, Orange brand); <code>mcc234-mnc00</code> (U.K., BT brand). <br>

+        <br>

+        If the device uses a radio connection  (GSM phone), the MCC will come from the SIM, and the MNC will come from the  network to which the device is attached. You might sometimes use the MCC alone, for example to include country-specific legal resources in your application. If your application specifies resources for a MCC/MNC  combination, those resources can only be used if both the MCC and the MNC match. </td>

+  </tr>

+    <tr>

+        <td>Language and region</td>

+        <td>The two letter <a href="http://www.loc.gov/standards/iso639-2/php/code_list.php">ISO

+                639-1</a> language code and two letter

+                <a href="http://www.iso.org/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html">ISO

+                3166-1-alpha-2</a> region code (preceded by lowercase &quot;r&quot;). For example 

+                <code>en-rUS</code>, <code>fr-rFR</code>, <code>es-rES</code>. <br>

+                <br>

+          The codes are case-sensitive: The language code is lowercase, and the country code is uppercase. You cannot specify a region alone, but you can specify a language alone, for example <code>en</code>, <code>fr</code>, <code>es</code>. </td>

+  </tr>

+    <tr>

+        <td>Screen orientation</td>

+        <td><code>port</code>, <code>land</code>, <code>square</code> </td>

+    </tr>

+    <tr>

+        <td>Screen pixel density</td>

+        <td><code>92dpi</code>, <code>108dpi</code>, etc. When Android selects which resource files to use, it handles screen density  differently than the other qualifiers. In step 1 of <a href="#best-match">How Android finds the best matching directory</a> (below),  screen density is always  considered to be a match. In step 4, if the qualifier being considered is screen density, Android will select the best final match at that point, without any need to move on to step 5. </td>

+  </tr>

+    <tr>

+        <td>Touchscreen type</td>

+        <td><code>notouch</code>, <code>stylus</code>, <code>finger</code></td>

+    </tr>

+    <tr>

+        <td>Whether the keyboard is available to the user</td>

+        <td><code>keysexposed</code>, <code>keyshidden</code>, <code>keyssoft</code> <br>

+          If your application has specific resources that should only be used with a soft keyboard, use the <code>keyssoft</code> value. If no <code>keyssoft</code> resources are available (only <code>keysexposed</code> and <code>keyshidden</code>) and the device  shows a soft keyboard,  the system will use <code>keysexposed</code> resources. </td>

+  </tr>

+    <tr>

+        <td>Primary text input method</td>

+        <td><code>nokeys</code>, <code>qwerty</code>, <code>12key</code> </td>

+    </tr>

+    <tr>

+        <td>Primary non-touchscreen<br />

+            navigation method</td>

+        <td><code>nonav</code>, <code>dpad</code>, <code>trackball</code>, <code>wheel</code> </td>

+    </tr>

+    <tr>

+        <td>Screen dimensions</td>

+        <td><code>320x240</code>, <code>640x480</code>, etc. The larger dimension

+            must be specified first. </td>

+    </tr>

+    <tr>

+      <td>SDK version</td>

+      <td>The SDK version supported by the device, for example <code>v3</code>. The Android 1.0 SDK is <code>v1, </code> the 1.1 SDK is <code>v2</code>, and the 1.5 SDK is <code>v3</code>.</td>

+  </tr>

+    <tr>

+      <td>(Minor version)</td>

+      <td>(You cannot currently    specify minor version. It is always set to 0.)</td>

+  </tr>

+</table>

+

+<p>This list does not include device-specific parameters such as carrier,

+branding, device/hardware, or manufacturer. Everything that an application

+needs to know about the device that it is running on is encoded via the

+resource qualifiers in the table above.</p>

+

+<p>All resource directories, qualified and unqualified, live under the <code>res/</code> folder. Here are some  guidelines on qualified resource directory names:</p>

+

+<ul>

+    <li>You can specify multiple qualifiers, separated by dashes. For example, <code>drawable-en-rUS-land</code> will apply to US-English

+    devices in landscape orientation. </li>

+    <li>The qualifiers must  be in the order listed in <a href="#table2">Table 2</a> above. For example:

+      <ul>

+        <li>Correct: <code>values-mcc460-nokeys/</code></li>

+        <li>Incorrect: <code>values-nokeys-mcc460/</code></li>

+      </ul>

+    </li>

+    <li>Values are case-sensitive. For example, a portrait-specific <code>drawable</code> directory must be named

+    <code>drawable-port</code>, not <code>drawable-PORT</code> or <code>drawable-Port</code>.</li>

+    <li>Only one value for each qualifier type is supported. For example, if you want to use exactly the same drawable files for Spain and France, you will need two  resource directories, such as <code>drawable-rES/</code> and <code>drawable-rFR/</code>, containing identical files. You cannot 

+        have a directory named <code>drawable-rES-rFR/</code>. </li>

+    <li>Qualified directories cannot be nested. For example, you cannot have <code>res/drawable/drawable-en</code>. </li>

+</ul>

+

+<h3>How resources are referenced in code</h3>

+<p>All resources will be referenced in code or resource reference syntax by

+    their simple, undecorated names. So if a resource were named this:<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<code>MyApp/res/drawable-port-92dpi/myimage.png</code><br />

+  It would be referenced as this:<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<code>R.drawable.myimage</code> (code)<br />

+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<code>&#064;drawable/myimage</code> (XML)</p>

+<p>If several drawable directories are available, Android will select one of them (as described below) and load  <code>myimage.png</code> from it.</p>

+<h3 id="best-match">How Android finds the best matching directory </h3>

+

+<p>Android will pick which of the various underlying resource files should be

+used at runtime, depending on the current configuration of the device. The example used here assumes the following device configuration:</p>

+<blockquote>

+  <p>Locale = <code>en-GB</code><br>

+  Screen orientation = <code>port</code><br>

+  Screen pixel density = <code>108dpi</code><br>

+    Touchscreen type = <code>notouch</code><br>

+    Primary text input method = <code>12key</code><br>

+  </p>

+</blockquote>

+<p>Here is how  Android  makes the selection: </p>

+<ol>

+    <li>

+            Eliminate  resource files that contradict the 

+            device configuration. For example, assume that the following resource directories are available for drawables. The <code>drawable-fr-rCA/</code> directory will be eliminated, because it contradicts the locale of the device.<br>

+<pre>MyApp/res/drawable/

+MyApp/res/drawable-en/

+<strike>MyApp/res/drawable-fr-rCA/</strike>

+MyApp/res/drawable-en-port/

+MyApp/res/drawable-en-notouch-12key/

+MyApp/res/drawable-port-92dpi/

+MyApp/res/drawable-port-notouch-12key</pre>

+      <strong>Exception: </strong>Screen pixel density is the one qualifier that is not used to eliminate files. Even though the screen density of the device is 108 dpi, <code>drawable-port-92dpi/</code> is not  eliminated from the list, because every screen density is considered to be a 

+        match at this point.</li>

+    <li>From <a href="#table2">Table 2</a>, pick the   highest-precedence qualifier that remains in the list. (Start with MCC, then move down through the list.) </li>

+  <li>Do any of the available resource directories include this qualifier?  </li>

+  <ul>

+    <li>If No, return to step 2 and look at the next qualifier listed in Table 2. In our example, the answer is &quot;no&quot; until we reach Language.</li>

+    <li>If Yes, move on to step 4.</li>

+  </ul>

+  <li>Eliminate resource directories that do not include this qualifier. In our example, we eliminate all the directories that do not include a language qualifier. </li>

+  <pre><strike>MyApp/res/drawable/</strike>

+MyApp/res/drawable-en/

+MyApp/res/drawable-en-port/

+MyApp/res/drawable-en-notouch-12key/

+<strike>MyApp/res/drawable-port-92dpi/</strike>

+<strike>MyApp/res/drawable-port-notouch-12key</strike></pre>

+  <strong>Exception:</strong> If the qualifier in question  is screen pixel density, Android will select the option that most closely matches the device, and the selection process will be complete. In general, Android will prefer scaling down a larger original image to scaling  up a smaller original image.<br><br></li>

+

+<li>Go back and repeat steps 2, 3, and 4 until only one choice remains. In the example, screen orientation is the next qualifier in the table for which we have any matches.

+    Eliminate resources that do not specify a screen orientation. </p>

+    <pre><strike>MyApp/res/drawable-en/</strike>

+MyApp/res/drawable-en-port/

+<strike>MyApp/res/drawable-en-notouch-12key/</strike></pre>

+  Only one choice remains, so that's it. When drawables are called for in this example application, the Android system will load resources from the <code>MyApp/res/drawable-en-port/</code> directory.

+</ol>

+<p class="note"><strong>Tip:</strong> The <em>precedence</em> of the qualifiers is more important than the number of qualifiers that exactly match the device. For example, in step 4 above, the last choice on the list includes three qualifiers that exactly match the device (orientation, touchscreen type, and input method), while <code>drawable-en</code> has only one parameter that matches (language). However, language has a higher precedence, so <code>drawable-port-notouch-12key</code> is out.</p>

+<p>This flowchart summarizes how Android selects resource directories to load.</p>

+<p><img src="res-selection-flowchart.png" alt="resource-selection" width="461" height="471" style="margin:15px"></p>

+<h3>Terminology</h3>

+<p>The resource system brings a number of different pieces together to

+form the final complete resource functionality.  To help understand the

+overall system, here are some brief definitions of the core concepts and

+components you will encounter in using it:</p>

+

+<p><strong>Asset</strong>: A single blob of data associated with an application. This

+includes object files compiled from the Java source code, graphics (such as PNG

+images), XML files, etc. These files are organized in a directory hierarchy

+that, during final packaging of the application, is bundled together into a

+single ZIP file.</p>

+

+<p><strong>aapt</strong>: Android Asset Packaging Tool. The tool that generates the 

+final ZIP file of application assets.  In addition to collecting raw assets 

+together, it also parses resource definitions into binary asset data.</p>

+

+<p><strong>Resource Table</strong>: A special asset that aapt generates for you,

+describing all of the resources contained in an application/package.

+This file is accessed for you by the Resources class; it is not touched

+directly by applications.</p>

+

+<p><strong>Resource</strong>: An entry in the Resource Table describing a single

+named value.  Broadly, there are two types of resources: primitives and

+bags.</p>

+

+<p><strong>Resource Identifier</strong>: In the Resource Table all resources are

+identified by a unique integer number.  In source code (resource descriptions,

+XML files, Java source code) you can use symbolic names that stand as constants for

+the actual resource identifier integer.</p>

+

+<p><strong>Primitive Resource</strong>: All primitive resources can be written as a

+simple string, using formatting to describe a variety of primitive types

+included in the resource system: integers, colors, strings, references to

+other resources, etc.  Complex resources, such as bitmaps and XML

+describes, are stored as a primitive string resource whose value is the path

+of the underlying Asset holding its actual data.</p>

+

+<p><strong>Bag Resource</strong>: A special kind of resource entry that, instead of a

+simple string, holds an arbitrary list of name/value pairs.  Each name is

+itself a resource identifier, and each value can hold

+the same kinds of string formatted data as a normal resource.  Bags also

+support inheritance: a bag can inherit the values from another bag, selectively

+replacing or extending them to generate its own contents.</p>

+

+<p><strong>Kind</strong>: The resource kind is a way to organize resource identifiers

+for various purposes.  For example, drawable resources are used to

+instantiate Drawable objects, so their data is a primitive resource containing

+either a color constant or string path to a bitmap or XML asset.  Other

+common resource kinds are string (localized string primitives), color

+(color primitives), layout (a string path to an XML asset describing a view

+layout), and style (a bag resource describing user interface attributes).

+There is also a standard "attr" resource kind, which defines the resource

+identifiers to be used for naming bag items and XML attributes</p>

+

+<p><strong>Style</strong>: The name of the resource kind containing bags that are used

+to supply a set of user interface attributes.  For example, a TextView class may

+be given a style resource that defines its text size, color, and alignment.

+In a layout XML file, you associate a style with a bag using the "style"

+attribute, whose value is the name of the style resource.</p>

+

+<p><strong>Style Class</strong>: Specifies a related set of attribute resources.

+This data is not placed in the resource table itself, but used to generate

+constants in the source code that make it easier for you to retrieve values out of

+a style resource and/or XML tag's attributes.  For example, the

+Android platform defines a "View" style class that

+contains all of the standard view attributes: padding, visibility,

+background, etc.; when View is inflated it uses this style class to

+retrieve those values from the XML file (at which point style and theme

+information is applied as approriate) and load them into its instance.</p>

+

+<p><strong>Configuration</strong>: For any particular resource identifier, there may be

+multiple different available values depending on the current configuration.

+The configuration includes the locale (language and country), screen

+orientation, etc.  The current configuration is used to

+select which resource values are in effect when the resource table is

+loaded.</p>

+

+<p><strong>Theme</strong>: A standard style resource that supplies global

+attribute values for a particular context.  For example, when writing an

+Activity the application developer can select a standard theme to use, such

+as the Theme.White or Theme.Black styles; this style supplies information

+such as the screen background image/color, default text color, button style,

+text editor style, text size, etc.  When inflating a layout resource, most

+values for widgets (the text color, selector, background) if not explicitly

+set will come from the current theme; style and attribute

+values supplied in the layout can also assign their value from explicitly

+named values in the theme attributes if desired.</p>

+

+<p><strong>Overlay</strong>: A resource table that does not define a new set of resources,

+but instead replaces the values of resources that are in another resource table.

+Like a configuration, this is applied at load time

+to the resource data; it can add new configuration values (for example

+strings in a new locale), replace existing values (for example change

+the standard white background image to a "Hello Kitty" background image),

+and modify resource bags (for example change the font size of the Theme.White

+style to have an 18 pt font size).  This is the facility that allows the

+user to select between different global appearances of their device, or

+download files with new appearances.</p>

+

+<h2>Resource Reference</h2>

+<p>The <a href="available-resources.html">Available Resources</a>

+document provides a detailed list of the various types of resource and how to use them

+from within the Java source code, or from other references.</p>

+

+<a name="i18n" id="i18n"></a>

+<h2>Internationalization and Localization</h2>

+<p class="note"><strong>Coming Soon:</strong> Internationalization and Localization are

+critical, but are also not quite ready yet in the current SDK. As the

+SDK matures, this section will contain information on the Internationalization

+and Localization features of the Android platform. In the meantime, it is a good

+idea to start by externalizing all strings, and practicing good structure in

+creating and using resources.</p>
\ No newline at end of file
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index fda584d..e2e93eb 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -16,14 +16,14 @@
 
 package android.graphics;
 
-import android.os.Parcelable;
 import android.os.Parcel;
+import android.os.Parcelable;
 
+import java.io.OutputStream;
 import java.nio.Buffer;
 import java.nio.ByteBuffer;
-import java.nio.ShortBuffer;
 import java.nio.IntBuffer;
-import java.io.OutputStream;
+import java.nio.ShortBuffer;
 
 public final class Bitmap implements Parcelable {
     /**
@@ -32,14 +32,14 @@
      * @see Bitmap#getDensityScale()
      * @see Bitmap#setDensityScale(float)
      *
-     * @hide pending API council approval 
+     * @hide pending API council approval
      */
     public static final float DENSITY_SCALE_UNKNOWN = -1.0f;
 
     // Note:  mNativeBitmap is used by FaceDetector_jni.cpp
     // Don't change/rename without updating FaceDetector_jni.cpp
     private final int mNativeBitmap;
-    
+
     private final boolean mIsMutable;
     private byte[] mNinePatchChunk;   // may be null
     private int mWidth = -1;
@@ -63,7 +63,7 @@
         if (nativeBitmap == 0) {
             throw new RuntimeException("internal error: native bitmap is 0");
         }
-        
+
         // we delete this in our finalizer
         mNativeBitmap = nativeBitmap;
         mIsMutable = isMutable;
@@ -83,7 +83,7 @@
      *
      * @see #setDensityScale(float)
      * @see #isAutoScalingEnabled()
-     * @see #setAutoScalingEnabled(boolean) 
+     * @see #setAutoScalingEnabled(boolean)
      * @see android.util.DisplayMetrics#DEFAULT_DENSITY
      * @see android.util.DisplayMetrics#density
      * @see #DENSITY_SCALE_UNKNOWN
@@ -105,7 +105,7 @@
      *
      * @see #getDensityScale()
      * @see #isAutoScalingEnabled()
-     * @see #setAutoScalingEnabled(boolean) 
+     * @see #setAutoScalingEnabled(boolean)
      * @see android.util.DisplayMetrics#DEFAULT_DENSITY
      * @see android.util.DisplayMetrics#density
      * @see #DENSITY_SCALE_UNKNOWN
@@ -126,7 +126,7 @@
      * <p>Auto scaling is turned off by default. If auto scaling is enabled but the
      * bitmap has an unknown density scale, then the bitmap will never be automatically
      * scaled at drawing time.</p>
-     * 
+     *
      * @return True if the bitmap must be scaled at drawing time, false otherwise.
      *
      * @see #setAutoScalingEnabled(boolean)
@@ -167,7 +167,7 @@
     public void setNinePatchChunk(byte[] chunk) {
         mNinePatchChunk = chunk;
     }
-    
+
     /**
      * Free up the memory associated with this bitmap's pixels, and mark the
      * bitmap as "dead", meaning it will throw an exception if getPixels() or
@@ -194,7 +194,7 @@
     public final boolean isRecycled() {
         return mRecycled;
     }
-    
+
     /**
      * This is called by methods that want to throw an exception if the bitmap
      * has already been recycled.
@@ -204,7 +204,7 @@
             throw new IllegalStateException(errorMessage);
         }
     }
-    
+
     /**
      * Common code for checking that x and y are >= 0
      *
@@ -246,16 +246,16 @@
             this.nativeInt = ni;
         }
         final int nativeInt;
-        
+
         /* package */ static Config nativeToConfig(int ni) {
             return sConfigs[ni];
         }
-        
+
         private static Config sConfigs[] = {
             null, null, ALPHA_8, null, RGB_565, ARGB_4444, ARGB_8888
         };
     }
-    
+
     /**
      * Copy the bitmap's pixels into the specified buffer (allocated by the
      * caller). An exception is thrown if the buffer is not large enough to
@@ -275,16 +275,16 @@
         } else {
             throw new RuntimeException("unsupported Buffer subclass");
         }
-        
+
         long bufferSize = (long)elements << shift;
         long pixelSize = (long)getRowBytes() * getHeight();
-        
+
         if (bufferSize < pixelSize) {
             throw new RuntimeException("Buffer not large enough for pixels");
         }
-        
+
         nativeCopyPixelsToBuffer(mNativeBitmap, dst);
-        
+
         // now update the buffer's position
         int position = dst.position();
         position += pixelSize >> shift;
@@ -299,7 +299,7 @@
      */
     public void copyPixelsFromBuffer(Buffer src) {
         checkRecycled("copyPixelsFromBuffer called on recycled bitmap");
-        
+
         int elements = src.remaining();
         int shift;
         if (src instanceof ByteBuffer) {
@@ -311,17 +311,17 @@
         } else {
             throw new RuntimeException("unsupported Buffer subclass");
         }
-        
+
         long bufferBytes = (long)elements << shift;
         long bitmapBytes = (long)getRowBytes() * getHeight();
-        
+
         if (bufferBytes < bitmapBytes) {
             throw new RuntimeException("Buffer not large enough for pixels");
         }
-        
+
         nativeCopyPixelsFromBuffer(mNativeBitmap, src);
     }
-        
+
     /**
      * Tries to make a new bitmap based on the dimensions of this bitmap,
      * setting the new bitmap's config to the one specified, and then copying
@@ -350,7 +350,7 @@
         if (m == null) {
             m = new Matrix();
         }
-        
+
         final int width = src.getWidth();
         final int height = src.getHeight();
         final float sx = dstWidth  / (float)width;
@@ -365,9 +365,9 @@
             }
         }
 
-        return b; 
+        return b;
     }
-    
+
     /**
      * Returns an immutable bitmap from the source bitmap. The new bitmap may
      * be the same object as source, or a copy may have been made.
@@ -390,7 +390,7 @@
     public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height) {
         return createBitmap(source, x, y, width, height, null, false);
     }
-    
+
     /**
      * Returns an immutable bitmap from subset of the source bitmap,
      * transformed by the optional matrix.
@@ -425,7 +425,7 @@
                 height == source.getHeight() && (m == null || m.isIdentity())) {
             return source;
         }
-        
+
         int neww = width;
         int newh = height;
         Canvas canvas = new Canvas();
@@ -470,7 +470,7 @@
 
         return bitmap;
     }
-    
+
     /**
      * Returns a mutable bitmap with the specified width and height.
      *
@@ -484,7 +484,7 @@
         bm.eraseColor(0);    // start with black/transparent pixels
         return bm;
     }
-    
+
     /**
      * Returns a immutable bitmap with the specified width and height, with each
      * pixel value set to the corresponding value in the colors array.
@@ -593,7 +593,7 @@
         return nativeCompress(mNativeBitmap, format.nativeInt, quality,
                               stream, new byte[WORKING_COMPRESS_STORAGE]);
     }
-    
+
     /**
      * Returns true if the bitmap is marked as mutable (i.e. can be drawn into)
      */
@@ -610,7 +610,7 @@
     public final int getHeight() {
         return mHeight == -1 ? mHeight = nativeHeight(mNativeBitmap) : mHeight;
     }
-    
+
     /**
      * Convenience method that returns the width of this bitmap divided
      * by the density scale factor.
@@ -648,7 +648,7 @@
     public final int getRowBytes() {
         return nativeRowBytes(mNativeBitmap);
     }
-    
+
     /**
      * If the bitmap's internal config is in one of the public formats, return
      * that config, otherwise return null.
@@ -690,7 +690,7 @@
         checkPixelAccess(x, y);
         return nativeGetPixel(mNativeBitmap, x, y);
     }
-    
+
     /**
      * Returns in pixels[] a copy of the data in the bitmap. Each value is
      * a packed int representing a {@link Color}. The stride parameter allows
@@ -722,7 +722,7 @@
         nativeGetPixels(mNativeBitmap, pixels, offset, stride,
                         x, y, width, height);
     }
-    
+
     /**
      * Shared code to check for illegal arguments passed to getPixel()
      * or setPixel()
@@ -779,7 +779,7 @@
             throw new ArrayIndexOutOfBoundsException();
         }
     }
-    
+
     /**
      * Write the specified {@link Color} into the bitmap (assuming it is
      * mutable) at the x,y coordinate.
@@ -799,10 +799,10 @@
         checkPixelAccess(x, y);
         nativeSetPixel(mNativeBitmap, x, y, color);
     }
-    
+
     /**
      * Replace pixels in the bitmap with the colors in the array. Each element
-     * in the array is a packed int prepresenting a {@link Color} 
+     * in the array is a packed int prepresenting a {@link Color}
      *
      * @param pixels   The colors to write to the bitmap
      * @param offset   The index of the first color to read from pixels[]
@@ -834,7 +834,7 @@
         nativeSetPixels(mNativeBitmap, pixels, offset, stride,
                         x, y, width, height);
     }
-    
+
     public static final Parcelable.Creator<Bitmap> CREATOR
             = new Parcelable.Creator<Bitmap>() {
         /**
@@ -884,7 +884,7 @@
     public Bitmap extractAlpha() {
         return extractAlpha(null, null);
     }
-    
+
     /**
      * Returns a new bitmap that captures the alpha values of the original.
      * These values may be affected by the optional Paint parameter, which
@@ -917,6 +917,22 @@
         return bm;
     }
 
+    /**
+     * Rebuilds any caches associated with the bitmap that are used for
+     * drawing it. In the case of purgeable bitmaps, this call will attempt to
+     * ensure that the pixels have been decoded.
+     * If this is called on more than one bitmap in sequence, the priority is
+     * given in LRU order (i.e. the last bitmap called will be given highest
+     * priority).
+     *
+     * For bitmaps with no associated caches, this call is effectively a no-op,
+     * and therefore is harmless.
+     */
+    public void prepareToDraw() {
+        nativePrepareToDraw(mNativeBitmap);
+    }
+
+    @Override
     protected void finalize() throws Throwable {
         try {
             nativeDestructor(mNativeBitmap);
@@ -924,7 +940,7 @@
             super.finalize();
         }
     }
-    
+
     //////////// native methods
 
     private static native Bitmap nativeCreate(int[] colors, int offset,
@@ -944,12 +960,12 @@
     private static native int nativeRowBytes(int nativeBitmap);
     private static native int nativeConfig(int nativeBitmap);
     private static native boolean nativeHasAlpha(int nativeBitmap);
-    
+
     private static native int nativeGetPixel(int nativeBitmap, int x, int y);
     private static native void nativeGetPixels(int nativeBitmap, int[] pixels,
                                                int offset, int stride, int x,
                                                int y, int width, int height);
-    
+
     private static native void nativeSetPixel(int nativeBitmap, int x, int y,
                                               int color);
     private static native void nativeSetPixels(int nativeBitmap, int[] colors,
@@ -969,6 +985,8 @@
                                                     int nativePaint,
                                                     int[] offsetXY);
 
+    private static native void nativePrepareToDraw(int nativeBitmap);
+
     /* package */ final int ni() {
         return mNativeBitmap;
     }
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 3db45f0..a7a8708 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -880,7 +880,9 @@
             mShape = state.mShape;
             mGradient = state.mGradient;
             mOrientation = state.mOrientation;
-            mColors = state.mColors.clone();
+            if (state.mColors != null) {
+                mColors = state.mColors.clone();
+            }
             if (state.mPositions != null) {
                 mPositions = state.mPositions.clone();
             }
diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h
index 2c4bc2a..85aeb30 100644
--- a/include/media/IMediaPlayer.h
+++ b/include/media/IMediaPlayer.h
@@ -23,6 +23,7 @@
 
 namespace android {
 
+class Parcel;
 class ISurface;
 
 class IMediaPlayer: public IInterface
@@ -45,6 +46,14 @@
     virtual status_t        setAudioStreamType(int type) = 0;
     virtual status_t        setLooping(int loop) = 0;
     virtual status_t        setVolume(float leftVolume, float rightVolume) = 0;
+
+    // Invoke a generic method on the player by using opaque parcels
+    // for the request and reply.
+    // @param request Parcel that must start with the media player
+    // interface token.
+    // @param[out] reply Parcel to hold the reply data. Cannot be null.
+    // @return OK if the invocation was made. PERMISSION_DENIED otherwise.
+    virtual status_t        invoke(const Parcel& request, Parcel *reply) = 0;
 };
 
 // ----------------------------------------------------------------------------
@@ -61,4 +70,3 @@
 }; // namespace android
 
 #endif // ANDROID_IMEDIAPLAYER_H
-
diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h
index 207e4e7..f6faf14 100644
--- a/include/media/IMediaPlayerService.h
+++ b/include/media/IMediaPlayerService.h
@@ -17,6 +17,7 @@
 #ifndef ANDROID_IMEDIAPLAYERSERVICE_H
 #define ANDROID_IMEDIAPLAYERSERVICE_H
 
+#include <utils/Errors.h>  // for status_t
 #include <utils/RefBase.h>
 #include <binder/IInterface.h>
 #include <binder/Parcel.h>
@@ -36,7 +37,6 @@
 
     virtual sp<IMediaRecorder>  createMediaRecorder(pid_t pid) = 0;
     virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid) = 0;
-
     virtual sp<IMediaPlayer>    create(pid_t pid, const sp<IMediaPlayerClient>& client, const char* url) = 0;
     virtual sp<IMediaPlayer>    create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length) = 0;
     virtual sp<IMemory>         decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat) = 0;
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index 7bf555a..21600b2 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -27,12 +27,15 @@
 
 namespace android {
 
+class Parcel;
+
 enum player_type {
     PV_PLAYER = 1,
     SONIVOX_PLAYER = 2,
     VORBIS_PLAYER = 3
 };
 
+
 #define DEFAULT_AUDIOSINK_BUFFERCOUNT 4
 #define DEFAULT_AUDIOSINK_BUFFERSIZE 1200
 #define DEFAULT_AUDIOSINK_SAMPLERATE 44100
@@ -45,7 +48,6 @@
 class MediaPlayerBase : public RefBase
 {
 public:
-
     // AudioSink: abstraction layer for audio output
     class AudioSink : public RefBase {
     public:
@@ -88,7 +90,14 @@
     virtual player_type playerType() = 0;
     virtual void        setNotifyCallback(void* cookie, notify_callback_f notifyFunc) {
                             mCookie = cookie; mNotify = notifyFunc; }
-
+    // Invoke a generic method on the player by using opaque parcels
+    // for the request and reply.
+    // @param request Parcel that is positioned at the start of the
+    //                data sent by the java layer.
+    // @param[out] reply Parcel to hold the reply data. Cannot be null.
+    // @return OK if the invocation was made successfully. A player
+    // not supporting the direct API should return INVALID_OPERATION.
+    virtual status_t    invoke(const Parcel& request, Parcel *reply) = 0;
 protected:
     virtual void        sendEvent(int msg, int ext1=0, int ext2=0) { if (mNotify) mNotify(mCookie, msg, ext1, ext2); }
 
diff --git a/include/media/PVPlayer.h b/include/media/PVPlayer.h
index 8122df6..eb4595b 100644
--- a/include/media/PVPlayer.h
+++ b/include/media/PVPlayer.h
@@ -52,6 +52,7 @@
     virtual status_t    reset();
     virtual status_t    setLooping(int loop);
     virtual player_type playerType() { return PV_PLAYER; }
+    virtual status_t    invoke(const Parcel& request, Parcel *reply);
 
     // make available to PlayerDriver
     void        sendEvent(int msg, int ext1=0, int ext2=0) { MediaPlayerBase::sendEvent(msg, ext1, ext2); }
diff --git a/include/media/ToneGenerator.h b/include/media/ToneGenerator.h
index 6b0cc8a..eafa661 100644
--- a/include/media/ToneGenerator.h
+++ b/include/media/ToneGenerator.h
@@ -71,6 +71,82 @@
         TONE_SUP_CONGESTION_ABBREV, // Abbreviated congestion: congestion tone limited to 4 seconds
         TONE_SUP_CONFIRM, // Confirm tone: a 350 Hz tone added to a 440 Hz tone repeated 3 times in a 100 ms on, 100 ms off cycle.
         TONE_SUP_PIP, // Pip tone: four bursts of 480 Hz tone (0.1 s on, 0.1 s off).
+
+        // CDMA Tones
+        TONE_CDMA_DIAL_TONE_LITE,
+        TONE_CDMA_NETWORK_USA_RINGBACK,
+        TONE_CDMA_INTERCEPT,
+        TONE_CDMA_ABBR_INTERCEPT,
+        TONE_CDMA_REORDER,
+        TONE_CDMA_ABBR_REORDER,
+        TONE_CDMA_NETWORK_BUSY,
+        TONE_CDMA_CONFIRM,
+        TONE_CDMA_ANSWER,
+        TONE_CDMA_NETWORK_CALLWAITING,
+        TONE_CDMA_PIP,
+
+        // ISDN
+        TONE_CDMA_CALL_SIGNAL_ISDN_NORMAL,  // ISDN Alert Normal
+        TONE_CDMA_CALL_SIGNAL_ISDN_INTERGROUP, // ISDN Intergroup
+        TONE_CDMA_CALL_SIGNAL_ISDN_SP_PRI, // ISDN SP PRI
+        TONE_CDMA_CALL_SIGNAL_ISDN_PAT3,  // ISDN Alert PAT3
+        TONE_CDMA_CALL_SIGNAL_ISDN_PING_RING, // ISDN Alert PING RING
+        TONE_CDMA_CALL_SIGNAL_ISDN_PAT5,  // ISDN Alert PAT5
+        TONE_CDMA_CALL_SIGNAL_ISDN_PAT6,  // ISDN Alert PAT6
+        TONE_CDMA_CALL_SIGNAL_ISDN_PAT7,  // ISDN Alert PAT7
+        // ISDN end
+
+        // IS54
+        TONE_CDMA_HIGH_L,  // IS54 High Pitch Long
+        TONE_CDMA_MED_L, // IS54 Med Pitch Long
+        TONE_CDMA_LOW_L, // IS54 Low Pitch Long
+        TONE_CDMA_HIGH_SS, // IS54 High Pitch Short Short
+        TONE_CDMA_MED_SS, // IS54 Medium Pitch Short Short
+        TONE_CDMA_LOW_SS, // IS54 Low Pitch Short Short
+        TONE_CDMA_HIGH_SSL, // IS54 High Pitch Short Short Long
+        TONE_CDMA_MED_SSL, // IS54 Medium  Pitch Short Short Long
+        TONE_CDMA_LOW_SSL, // IS54 Low  Pitch Short Short Long
+        TONE_CDMA_HIGH_SS_2, // IS54 High Pitch Short Short 2
+        TONE_CDMA_MED_SS_2, // IS54 Med Pitch Short Short 2
+        TONE_CDMA_LOW_SS_2, // IS54 Low  Pitch Short Short 2
+        TONE_CDMA_HIGH_SLS, // IS54 High Pitch Short Long Short
+        TONE_CDMA_MED_SLS, // IS54 Med Pitch Short Long Short
+        TONE_CDMA_LOW_SLS, // IS54 Low Pitch Short Long Short
+        TONE_CDMA_HIGH_S_X4, // IS54 High Pitch Short Short Short Short
+        TONE_CDMA_MED_S_X4, // IS54 Med Pitch Short Short Short Short
+        TONE_CDMA_LOW_S_X4, // IS54 Low Pitch Short Short Short Short
+        TONE_CDMA_HIGH_PBX_L, // PBX High Pitch Long
+        TONE_CDMA_MED_PBX_L, // PBX Med Pitch Long
+        TONE_CDMA_LOW_PBX_L, // PBX Low  Pitch Long
+        TONE_CDMA_HIGH_PBX_SS, // PBX High Short Short
+        TONE_CDMA_MED_PBX_SS, // PBX Med Short Short
+        TONE_CDMA_LOW_PBX_SS, // PBX Low  Short Short
+        TONE_CDMA_HIGH_PBX_SSL, // PBX High Short Short Long
+        TONE_CDMA_MED_PBX_SSL, // PBX Med Short Short Long
+        TONE_CDMA_LOW_PBX_SSL,  // PBX Low Short Short Long
+        TONE_CDMA_HIGH_PBX_SLS, // PBX High  SLS
+        TONE_CDMA_MED_PBX_SLS,  // PBX Med SLS
+        TONE_CDMA_LOW_PBX_SLS, // PBX Low SLS
+        TONE_CDMA_HIGH_PBX_S_X4, // PBX High SSSS
+        TONE_CDMA_MED_PBX_S_X4, // PBX Med SSSS
+        TONE_CDMA_LOW_PBX_S_X4, // PBX LOW SSSS
+        //IS54 end
+        // proprietary
+        TONE_CDMA_ALERT_NETWORK_LITE,
+        TONE_CDMA_ALERT_AUTOREDIAL_LITE,
+        TONE_CDMA_ONE_MIN_BEEP,
+        TONE_CDMA_KEYPAD_VOLUME_KEY_LITE,
+        TONE_CDMA_PRESSHOLDKEY_LITE,
+        TONE_CDMA_ALERT_INCALL_LITE,
+        TONE_CDMA_EMERGENCY_RINGBACK,
+        TONE_CDMA_ALERT_CALL_GUARD,
+        TONE_CDMA_SOFT_ERROR_LITE,
+        TONE_CDMA_CALLDROP_LITE,
+        // proprietary end
+        TONE_CDMA_NETWORK_BUSY_ONE_SHOT,
+        TONE_CDMA_ABBR_ALERT,
+        TONE_CDMA_SIGNAL_OFF,
+        //CDMA end
         NUM_TONES,
         NUM_SUP_TONES = LAST_SUP_TONE-FIRST_SUP_TONE+1
     };
@@ -125,7 +201,7 @@
     static const unsigned char sToneMappingTable[NUM_REGIONS-1][NUM_SUP_TONES];
 
     static const unsigned int TONEGEN_MAX_WAVES = 3;     // Maximun number of sine waves in a tone segment
-    static const unsigned int TONEGEN_MAX_SEGMENTS = 5;  // Maximun number of segments in a tone descriptor
+    static const unsigned int TONEGEN_MAX_SEGMENTS = 12;  // Maximun number of segments in a tone descriptor
     static const unsigned int TONEGEN_INF = 0xFFFFFFFF;  // Represents infinite time duration
     static const float TONEGEN_GAIN = 0.9;  // Default gain passed to  WaveGenerator().
 
@@ -140,6 +216,8 @@
     //        correspond to tone ON state and segments with odd index to OFF state.
     //        The data stored in segments[] is the duration of the corresponding period in ms.
     //        The first segment encountered with a 0 duration    indicates that no more segment follows.
+    //    - loopCnt - Number of times to repeat a sequence of seqments after playing this
+    //    - loopIndx - The segment index to go back and play is loopcnt > 0
     //    - repeatCnt indicates the number of times the sequence described by segments[] array must be repeated.
     //        When the tone generator encounters the first 0 duration segment, it will compare repeatCnt to mCurCount.
     //        If mCurCount > repeatCnt, the tone is stopped automatically. Otherwise, tone sequence will be
@@ -150,6 +228,8 @@
     public:
         unsigned int duration;
         unsigned short waveFreq[TONEGEN_MAX_WAVES+1];
+        unsigned short loopCnt;
+        unsigned short loopIndx;
     };
 
     class ToneDescriptor {
@@ -174,6 +254,8 @@
     const ToneDescriptor *mpToneDesc;  // pointer to active tone descriptor
     const ToneDescriptor *mpNewToneDesc;  // pointer to next active tone descriptor
 
+    unsigned short mLoopCounter; // Current tone loopback count
+
     int mSamplingRate;  // AudioFlinger Sampling rate
     AudioTrack *mpAudioTrack;  // Pointer to audio track used for playback
     Mutex mLock;  // Mutex to control concurent access to ToneGenerator object from audio callback and application API
diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h
index ffb325d..dd8ea19 100644
--- a/include/media/mediaplayer.h
+++ b/include/media/mediaplayer.h
@@ -151,7 +151,7 @@
             void            notify(int msg, int ext1, int ext2);
     static  sp<IMemory>     decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
     static  sp<IMemory>     decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
-
+            status_t        invoke(const Parcel& request, Parcel *reply);
 private:
             void            clear_l();
             status_t        seekTo_l(int msec);
diff --git a/include/private/opengles/gl_context.h b/include/private/opengles/gl_context.h
index 3b40677..523aed0 100644
--- a/include/private/opengles/gl_context.h
+++ b/include/private/opengles/gl_context.h
@@ -458,7 +458,7 @@
     void validate();
     matrixf_t& top() { return stack[depth]; }
     const matrixf_t& top() const { return stack[depth]; }
-    const uint32_t top_ops() const { return ops[depth]; }
+    uint32_t top_ops() const { return ops[depth]; }
     inline bool isRigidBody() const {
         return !(ops[depth] & ~(OP_TRANSLATE|OP_UNIFORM_SCALE|OP_ROTATE));
     }
diff --git a/include/ui/Camera.h b/include/ui/Camera.h
index 048bdd5..bbc21c4 100644
--- a/include/ui/Camera.h
+++ b/include/ui/Camera.h
@@ -86,10 +86,13 @@
 class Mutex;
 class String8;
 
-typedef void (*shutter_callback)(void *cookie);
-typedef void (*frame_callback)(const sp<IMemory>& mem, void *cookie);
-typedef void (*autofocus_callback)(bool focused, void *cookie);
-typedef void (*error_callback)(status_t err, void *cookie);
+// ref-counted object for callbacks
+class CameraListener: virtual public RefBase
+{
+public:
+    virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2) = 0;
+    virtual void postData(int32_t msgType, const sp<IMemory>& dataPtr) = 0;
+};
 
 class Camera : public BnCameraClient, public IBinder::DeathRecipient
 {
@@ -144,13 +147,8 @@
             // get preview/capture parameters - key/value pairs
             String8     getParameters() const;
 
-            void        setShutterCallback(shutter_callback cb, void *cookie);
-            void        setRawCallback(frame_callback cb, void *cookie);
-            void        setJpegCallback(frame_callback cb, void *cookie);
-            void        setRecordingCallback(frame_callback cb, void *cookie);
-            void        setPreviewCallback(frame_callback cb, void *cookie, int preview_callback_flag = FRAME_CALLBACK_FLAG_NOOP);
-            void        setErrorCallback(error_callback cb, void *cookie);
-            void        setAutoFocusCallback(autofocus_callback cb, void *cookie);
+            void        setListener(const sp<CameraListener>& listener);
+            void        setPreviewCallbackFlags(int preview_callback_flag);
 
     // ICameraClient interface
     virtual void        notifyCallback(int32_t msgType, int32_t ext, int32_t ext2);
@@ -160,6 +158,8 @@
 
 private:
                         Camera();
+                        Camera(const Camera&);
+                        Camera& operator=(const Camera);
                         virtual void binderDied(const wp<IBinder>& who);
 
             class DeathNotifier: public IBinder::DeathRecipient
@@ -179,20 +179,7 @@
             sp<ICamera>         mCamera;
             status_t            mStatus;
 
-            shutter_callback    mShutterCallback;
-            void                *mShutterCallbackCookie;
-            frame_callback      mRawCallback;
-            void                *mRawCallbackCookie;
-            frame_callback      mJpegCallback;
-            void                *mJpegCallbackCookie;
-            frame_callback      mPreviewCallback;
-            void                *mPreviewCallbackCookie;
-            frame_callback      mRecordingCallback;
-            void                *mRecordingCallbackCookie;
-            error_callback      mErrorCallback;
-            void                *mErrorCallbackCookie;
-            autofocus_callback  mAutoFocusCallback;
-            void                *mAutoFocusCallbackCookie;
+            sp<CameraListener>  mListener;
 
             friend class DeathNotifier;
 
diff --git a/include/utils/BackupHelpers.h b/include/utils/BackupHelpers.h
index c78b99a..b1f5045 100644
--- a/include/utils/BackupHelpers.h
+++ b/include/utils/BackupHelpers.h
@@ -43,6 +43,7 @@
 struct FileState {
     int modTime_sec;
     int modTime_nsec;
+    int mode;
     int size;
     int crc32;
     int nameLen;
@@ -71,6 +72,8 @@
     status_t WriteEntityHeader(const String8& key, size_t dataSize);
     status_t WriteEntityData(const void* data, size_t size);
 
+    void SetKeyPrefix(const String8& keyPrefix);
+
 private:
     explicit BackupDataWriter();
     status_t write_padding_for(int n);
@@ -79,6 +82,7 @@
     status_t m_status;
     ssize_t m_pos;
     int m_entityCount;
+    String8 m_keyPrefix;
 };
 
 /**
@@ -133,6 +137,7 @@
 
 private:
     void* m_buf;
+    bool m_loggedUnknownMetadata;
     KeyedVector<String8,FileRec> m_files;
 };
 
diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h
index 68f9233..f1029b7 100644
--- a/include/utils/ResourceTypes.h
+++ b/include/utils/ResourceTypes.h
@@ -71,7 +71,7 @@
  * The relative sizes of the stretchy segments indicates the relative
  * amount of stretchiness of the regions bordered by the segments.  For
  * example, regions 3, 7 and 11 above will take up more horizontal space
- * than regions 1, 5 and 9 since the horizonal segment associated with
+ * than regions 1, 5 and 9 since the horizontal segment associated with
  * the first set of regions is larger than the other set of regions.  The
  * ratios of the amount of horizontal (or vertical) space taken by any
  * two stretchable slices is exactly the ratio of their corresponding
@@ -87,7 +87,7 @@
  * the leftmost slices always start at x=0 and the rightmost slices
  * always end at the end of the image. So, for example, the regions 0,
  * 4 and 8 (which are fixed along the X axis) start at x value 0 and
- * go to xDiv[0] amd slices 2, 6 and 10 start at xDiv[1] and end at
+ * go to xDiv[0] and slices 2, 6 and 10 start at xDiv[1] and end at
  * xDiv[2].
  *
  * The array pointed to by the colors field lists contains hints for
@@ -626,25 +626,25 @@
     event_code_t next();
 
     // These are available for all nodes:
-    const int32_t getCommentID() const;
+    int32_t getCommentID() const;
     const uint16_t* getComment(size_t* outLen) const;
-    const uint32_t getLineNumber() const;
+    uint32_t getLineNumber() const;
     
     // This is available for TEXT:
-    const int32_t getTextID() const;
+    int32_t getTextID() const;
     const uint16_t* getText(size_t* outLen) const;
     ssize_t getTextValue(Res_value* outValue) const;
     
     // These are available for START_NAMESPACE and END_NAMESPACE:
-    const int32_t getNamespacePrefixID() const;
+    int32_t getNamespacePrefixID() const;
     const uint16_t* getNamespacePrefix(size_t* outLen) const;
-    const int32_t getNamespaceUriID() const;
+    int32_t getNamespaceUriID() const;
     const uint16_t* getNamespaceUri(size_t* outLen) const;
     
     // These are available for START_TAG and END_TAG:
-    const int32_t getElementNamespaceID() const;
+    int32_t getElementNamespaceID() const;
     const uint16_t* getElementNamespace(size_t* outLen) const;
-    const int32_t getElementNameID() const;
+    int32_t getElementNameID() const;
     const uint16_t* getElementName(size_t* outLen) const;
     
     // Remaining methods are for retrieving information about attributes
@@ -653,14 +653,14 @@
     size_t getAttributeCount() const;
     
     // Returns -1 if no namespace, -2 if idx out of range.
-    const int32_t getAttributeNamespaceID(size_t idx) const;
+    int32_t getAttributeNamespaceID(size_t idx) const;
     const uint16_t* getAttributeNamespace(size_t idx, size_t* outLen) const;
     
-    const int32_t getAttributeNameID(size_t idx) const;
+    int32_t getAttributeNameID(size_t idx) const;
     const uint16_t* getAttributeName(size_t idx, size_t* outLen) const;
-    const uint32_t getAttributeNameResID(size_t idx) const;
+    uint32_t getAttributeNameResID(size_t idx) const;
     
-    const int32_t getAttributeValueStringID(size_t idx) const;
+    int32_t getAttributeValueStringID(size_t idx) const;
     const uint16_t* getAttributeStringValue(size_t idx, size_t* outLen) const;
     
     int32_t getAttributeDataType(size_t idx) const;
diff --git a/libs/rs/Android.mk b/libs/rs/Android.mk
index 06c0595..f5297f8 100644
--- a/libs/rs/Android.mk
+++ b/libs/rs/Android.mk
@@ -85,6 +85,7 @@
 	rsContext.cpp \
 	rsDevice.cpp \
 	rsElement.cpp \
+	rsLight.cpp \
 	rsLocklessFifo.cpp \
 	rsObjectBase.cpp \
 	rsMatrix.cpp \
diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h
index 2b33419..734fba7 100644
--- a/libs/rs/RenderScript.h
+++ b/libs/rs/RenderScript.h
@@ -38,6 +38,7 @@
 typedef void * RsScriptBasicTemp;
 typedef void * RsTriangleMesh;
 typedef void * RsType;
+typedef void * RsLight;
 
 typedef void * RsProgramVertex;
 typedef void * RsProgramFragment;
diff --git a/libs/rs/RenderScriptEnv.h b/libs/rs/RenderScriptEnv.h
index 221ab41..53de1f1 100644
--- a/libs/rs/RenderScriptEnv.h
+++ b/libs/rs/RenderScriptEnv.h
@@ -14,6 +14,7 @@
 typedef void * RsType;
 typedef void * RsProgramFragment;
 typedef void * RsProgramFragmentStore;
+typedef void * RsLight;
 
 
 typedef struct {
diff --git a/libs/rs/java/Film/src/com/android/film/FilmRS.java b/libs/rs/java/Film/src/com/android/film/FilmRS.java
index 5c6a6fa..2711bf0 100644
--- a/libs/rs/java/Film/src/com/android/film/FilmRS.java
+++ b/libs/rs/java/Film/src/com/android/film/FilmRS.java
@@ -85,6 +85,7 @@
     private RenderScript.Allocation mAllocState;
     private RenderScript.Allocation mAllocPV;
     private RenderScript.TriangleMesh mMesh;
+    private RenderScript.Light mLight;
 
     private float[] mBufferPos;
     private float[] mBufferPV;
@@ -144,6 +145,10 @@
         mPV = mRS.programVertexCreate();
         mPV.setName("PV");
 
+        mRS.lightBegin();
+        mLight = mRS.lightCreate();
+        mLight.setPosition(0, -0.5f, -1.0f);
+
         Log.e("rs", "Done loading named");
     }
 
diff --git a/libs/rs/java/Fountain/res/raw/fountain.c b/libs/rs/java/Fountain/res/raw/fountain.c
index 8a55406..6919565 100644
--- a/libs/rs/java/Fountain/res/raw/fountain.c
+++ b/libs/rs/java/Fountain/res/raw/fountain.c
@@ -3,7 +3,7 @@
 #pragma version(1)
 #pragma stateVertex(default)
 #pragma stateFragment(PgmFragBackground)
-#pragma stateFragmentStore(parent)
+#pragma stateFragmentStore(PFSReplace)
 
 
 int main(int launchID) {
@@ -36,6 +36,7 @@
 
     drawRect(0, 256, 0, 512);
     contextBindProgramFragment(NAMED_PgmFragParts);
+    contextBindProgramFragmentStore(NAMED_PFSBlend);
 
     if (touch) {
         newPart = loadI32(2, 0);
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 467115a..745635f 100644
--- a/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
+++ b/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
@@ -56,6 +56,7 @@
     private RenderScript.Allocation mVertAlloc;
     private RenderScript.Script mScript;
     private RenderScript.ProgramFragmentStore mPFS;
+    private RenderScript.ProgramFragmentStore mPFS2;
     private RenderScript.ProgramFragment mPF;
     private RenderScript.ProgramFragment mPF2;
     private RenderScript.Allocation mTexture;
@@ -79,20 +80,29 @@
             Bitmap b = bd.getBitmap();
             mTexture = mRS.allocationCreateFromBitmap(b,
                                                       RenderScript.ElementPredefined.RGB_565,
-                                                      true);
+                                                      false);
             mTexture.uploadToTexture(0);
         }
 
         mRS.programFragmentStoreBegin(null, null);
         mRS.programFragmentStoreBlendFunc(RenderScript.BlendSrcFunc.SRC_ALPHA, RenderScript.BlendDstFunc.ONE);
         mRS.programFragmentStoreDepthFunc(RenderScript.DepthFunc.ALWAYS);
+        mRS.programFragmentStoreDepthMask(false);
+        mRS.programFragmentStoreDitherEnable(false);
         mPFS = mRS.programFragmentStoreCreate();
-        mPFS.setName("MyBlend");
-        mRS.contextBindProgramFragmentStore(mPFS);
+        mPFS.setName("PFSBlend");
+
+        mRS.programFragmentStoreBegin(null, null);
+        mRS.programFragmentStoreDepthFunc(RenderScript.DepthFunc.ALWAYS);
+        mRS.programFragmentStoreDepthMask(false);
+        mRS.programFragmentStoreDitherEnable(false);
+        mPFS2 = mRS.programFragmentStoreCreate();
+        mPFS2.setName("PFSReplace");
+        mRS.contextBindProgramFragmentStore(mPFS2);
 
         mRS.samplerBegin();
-        mRS.samplerSet(RenderScript.SamplerParam.FILTER_MAG, RenderScript.SamplerValue.LINEAR);
-        mRS.samplerSet(RenderScript.SamplerParam.FILTER_MIN, RenderScript.SamplerValue.LINEAR);
+        mRS.samplerSet(RenderScript.SamplerParam.FILTER_MAG, RenderScript.SamplerValue.NEAREST);
+        mRS.samplerSet(RenderScript.SamplerParam.FILTER_MIN, RenderScript.SamplerValue.NEAREST);
         mSampler = mRS.samplerCreate();
 
 
diff --git a/libs/rs/java/RenderScript/android/renderscript/RSSurfaceView.java b/libs/rs/java/RenderScript/android/renderscript/RSSurfaceView.java
index 3d37c13..3835793 100644
--- a/libs/rs/java/RenderScript/android/renderscript/RSSurfaceView.java
+++ b/libs/rs/java/RenderScript/android/renderscript/RSSurfaceView.java
@@ -40,7 +40,7 @@
     public RSSurfaceView(Context context) {
         super(context);
         init();
-        Log.v("***", "RSSurfaceView");
+        Log.v(RenderScript.LOG_TAG, "RSSurfaceView");
     }
 
     /**
@@ -50,7 +50,7 @@
     public RSSurfaceView(Context context, AttributeSet attrs) {
         super(context, attrs);
         init();
-        Log.v("***", "RSSurfaceView");
+        Log.v(RenderScript.LOG_TAG, "RSSurfaceView");
     }
 
     private void init() {
@@ -66,7 +66,7 @@
      * not normally called or subclassed by clients of RSSurfaceView.
      */
     public void surfaceCreated(SurfaceHolder holder) {
-        Log.v("***", "surfaceCreated");
+        Log.v(RenderScript.LOG_TAG, "surfaceCreated");
         mSurfaceHolder = holder;
         //mGLThread.surfaceCreated();
     }
@@ -77,7 +77,7 @@
      */
     public void surfaceDestroyed(SurfaceHolder holder) {
         // Surface will be destroyed when we return
-        Log.v("***", "surfaceDestroyed");
+        Log.v(RenderScript.LOG_TAG, "surfaceDestroyed");
         //mGLThread.surfaceDestroyed();
     }
 
@@ -86,7 +86,7 @@
      * not normally called or subclassed by clients of RSSurfaceView.
      */
     public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
-        Log.v("***", "surfaceChanged");
+        Log.v(RenderScript.LOG_TAG, "surfaceChanged");
 
         //mGLThread.onWindowResize(w, h);
     }
@@ -98,7 +98,7 @@
      * Must not be called before a renderer has been set.
      */
     public void onPause() {
-        Log.v("***", "onPause");
+        Log.v(RenderScript.LOG_TAG, "onPause");
         //mGLThread.onPause();
     }
 
@@ -110,7 +110,7 @@
      * Must not be called before a renderer has been set.
      */
     public void onResume() {
-        Log.v("***", "onResume");
+        Log.v(RenderScript.LOG_TAG, "onResume");
         //mGLThread.onResume();
     }
 
@@ -121,7 +121,7 @@
      * @param r the runnable to be run on the GL rendering thread.
      */
     public void queueEvent(Runnable r) {
-        Log.v("***", "queueEvent");
+        Log.v(RenderScript.LOG_TAG, "queueEvent");
         //mGLThread.queueEvent(r);
     }
 
@@ -139,14 +139,14 @@
     // ----------------------------------------------------------------------
 
     public RenderScript createRenderScript() {
-        Log.v("***", "createRenderScript 1");
+        Log.v(RenderScript.LOG_TAG, "createRenderScript 1");
         Surface sur = null;
         while ((sur == null) || (mSurfaceHolder == null)) {
             sur = getHolder().getSurface();
         }
-        Log.v("***", "createRenderScript 2");
+        Log.v(RenderScript.LOG_TAG, "createRenderScript 2");
         RenderScript rs = new RenderScript(sur);
-        Log.v("***", "createRenderScript 3 rs");
+        Log.v(RenderScript.LOG_TAG, "createRenderScript 3 rs");
         return rs;
     }
 
diff --git a/libs/rs/java/RenderScript/android/renderscript/RenderScript.java b/libs/rs/java/RenderScript/android/renderscript/RenderScript.java
index 4d5c4a0..a9db15f 100644
--- a/libs/rs/java/RenderScript/android/renderscript/RenderScript.java
+++ b/libs/rs/java/RenderScript/android/renderscript/RenderScript.java
@@ -32,7 +32,7 @@
 import android.graphics.Color;
 
 public class RenderScript {
-    private static final String LOG_TAG = "libRS_jni";
+    static final String LOG_TAG = "libRS_jni";
     private static final boolean DEBUG  = false;
     private static final boolean LOG_ENABLED = DEBUG ? Config.LOGD : Config.LOGV;
 
@@ -157,6 +157,14 @@
     native private void nProgramVertexSetTextureMatrixEnable(boolean enable);
     native private int  nProgramVertexCreate();
 
+    native private void nLightBegin();
+    native private void nLightSetIsMono(boolean isMono);
+    native private void nLightSetIsLocal(boolean isLocal);
+    native private int  nLightCreate();
+    native private void nLightDestroy(int l);
+    native private void nLightSetColor(int l, float r, float g, float b);
+    native private void nLightSetPosition(int l, float x, float y, float z);
+
 
     private int     mDev;
     private int     mContext;
@@ -869,6 +877,44 @@
         return new Sampler(id);
     }
 
+    //////////////////////////////////////////////////////////////////////////////////
+    // Light
+
+    public class Light extends BaseObj {
+        Light(int id) {
+            mID = id;
+        }
+
+        public void destroy() {
+            nLightDestroy(mID);
+            mID = 0;
+        }
+
+        public void setColor(float r, float g, float b) {
+            nLightSetColor(mID, r, g, b);
+        }
+
+        public void setPosition(float x, float y, float z) {
+            nLightSetPosition(mID, x, y, z);
+        }
+    }
+
+    public void lightBegin() {
+        nLightBegin();
+    }
+
+    public void lightSetIsMono(boolean isMono) {
+        nLightSetIsMono(isMono);
+    }
+
+    public void lightSetIsLocal(boolean isLocal) {
+        nLightSetIsLocal(isLocal);
+    }
+
+    public Light lightCreate() {
+        int id = nLightCreate();
+        return new Light(id);
+    }
 
     ///////////////////////////////////////////////////////////////////////////////////
     // Root state
diff --git a/libs/rs/jni/RenderScript_jni.cpp b/libs/rs/jni/RenderScript_jni.cpp
index dcf3850..5677bb7 100644
--- a/libs/rs/jni/RenderScript_jni.cpp
+++ b/libs/rs/jni/RenderScript_jni.cpp
@@ -14,19 +14,20 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "libRS_jni"
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <math.h>
-
 #include <utils/misc.h>
-#include <utils/Log.h>
 
 #include <ui/Surface.h>
 
 #include <core/SkBitmap.h>
 
+
 #include "jni.h"
 #include "JNIHelp.h"
 #include "android_runtime/AndroidRuntime.h"
@@ -107,7 +108,6 @@
     if (window == NULL)
         goto not_valid_surface;
 
-    LOGE("nContextCreate 5");
     return (jint)rsContextCreate((RsDevice)dev, window, ver);
 }
 
@@ -880,10 +880,67 @@
 nSamplerCreate(JNIEnv *_env, jobject _this)
 {
     RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
-    LOG_API("nSamplerCreate, con(%p), script(%p)", con, (RsScript)script);
+    LOG_API("nSamplerCreate, con(%p)", con);
     return (jint)rsSamplerCreate();
 }
 
+// ---------------------------------------------------------------------------
+
+static void
+nLightBegin(JNIEnv *_env, jobject _this)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nLightBegin, con(%p)", con);
+    rsLightBegin();
+}
+
+static void
+nLightSetIsMono(JNIEnv *_env, jobject _this, jboolean isMono)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nLightSetIsMono, con(%p), isMono(%i)", con, isMono);
+    rsLightSetMonochromatic(isMono);
+}
+
+static void
+nLightSetIsLocal(JNIEnv *_env, jobject _this, jboolean isLocal)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nLightSetIsLocal, con(%p), isLocal(%i)", con, isLocal);
+    rsLightSetLocal(isLocal);
+}
+
+static jint
+nLightCreate(JNIEnv *_env, jobject _this)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nLightCreate, con(%p)", con);
+    return (jint)rsLightCreate();
+}
+
+static void
+nLightDestroy(JNIEnv *_env, jobject _this, jint light)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nLightDestroy, con(%p), light(%p)", con, (RsLight)light);
+    rsLightDestroy((RsLight)light);
+}
+
+static void
+nLightSetColor(JNIEnv *_env, jobject _this, jint light, float r, float g, float b)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nLightSetColor, con(%p), light(%p), r(%f), g(%f), b(%f)", con, (RsLight)light, r, g, b);
+    rsLightSetColor((RsLight)light, r, g, b);
+}
+
+static void
+nLightSetPosition(JNIEnv *_env, jobject _this, jint light, float x, float y, float z)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nLightSetPosition, con(%p), light(%p), x(%f), y(%f), z(%f)", con, (RsLight)light, x, y, z);
+    rsLightSetPosition((RsLight)light, x, y, z);
+}
 
 // ---------------------------------------------------------------------------
 
@@ -978,6 +1035,14 @@
 {"nProgramVertexSetTextureMatrixEnable",   "(Z)V",                         (void*)nProgramVertexSetTextureMatrixEnable },
 {"nProgramVertexCreate",           "()I",                                  (void*)nProgramVertexCreate },
 
+{"nLightBegin",                    "()V",                                  (void*)nLightBegin },
+{"nLightSetIsMono",                "(Z)V",                                 (void*)nLightSetIsMono },
+{"nLightSetIsLocal",               "(Z)V",                                 (void*)nLightSetIsLocal },
+{"nLightCreate",                   "()I",                                  (void*)nLightCreate },
+{"nLightDestroy",                  "(I)V",                                 (void*)nLightDestroy },
+{"nLightSetColor",                 "(IFFF)V",                              (void*)nLightSetColor },
+{"nLightSetPosition",              "(IFFF)V",                              (void*)nLightSetPosition },
+
 {"nContextBindRootScript",         "(I)V",                                 (void*)nContextBindRootScript },
 {"nContextBindProgramFragmentStore","(I)V",                                (void*)nContextBindProgramFragmentStore },
 {"nContextBindProgramFragment",    "(I)V",                                 (void*)nContextBindProgramFragment },
@@ -1003,8 +1068,6 @@
     JNIEnv* env = NULL;
     jint result = -1;
 
-    LOGE("****************************************************\n");
-
     if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
         LOGE("ERROR: GetEnv failed\n");
         goto bail;
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index dd489b8..fadda59 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -403,3 +403,36 @@
 	param bool enable
 	}
 
+LightBegin {
+	}
+
+LightSetLocal {
+	param bool isLocal
+	}
+
+LightSetMonochromatic {
+	param bool isMono
+	}
+
+LightCreate {
+	ret RsLight light
+	}
+
+LightDestroy {
+	param RsLight light
+	}
+
+LightSetPosition {
+	param RsLight light
+	param float x
+	param float y
+	param float z
+	}
+
+LightSetColor {
+	param RsLight light
+	param float r
+	param float g
+	param float b
+	}
+
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
index 3a01a75..bc14eac 100644
--- a/libs/rs/rsAllocation.cpp
+++ b/libs/rs/rsAllocation.cpp
@@ -16,6 +16,9 @@
 
 #include "rsContext.h"
 
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
 using namespace android;
 using namespace android::renderscript;
 
@@ -47,7 +50,6 @@
 
 Allocation::~Allocation()
 {
-    LOGE("Allocation %p destryed", this);
 }
 
 void Allocation::setCpuWritable(bool)
@@ -76,8 +78,6 @@
     //rsAssert(!mTextureId);
     rsAssert(lodOffset < mType->getLODCount());
 
-    //LOGE("uploadToTexture  %i,  lod %i", mTextureID, lodOffset);
-
     GLenum type = mType->getElement()->getGLType();
     GLenum format = mType->getElement()->getGLFormat();
 
@@ -106,8 +106,6 @@
     rsAssert(!mType->getDimY());
     rsAssert(!mType->getDimZ());
 
-    //LOGE("uploadToTexture  %i,  lod %i", mTextureID, lodOffset);
-
     if (!mBufferID) {
         glGenBuffers(1, &mBufferID);
     }
diff --git a/libs/rs/rsComponent.h b/libs/rs/rsComponent.h
index 205e575..e1b0585 100644
--- a/libs/rs/rsComponent.h
+++ b/libs/rs/rsComponent.h
@@ -17,11 +17,7 @@
 #ifndef ANDROID_RS_STRUCTURED_COMPONENT_H
 #define ANDROID_RS_STRUCTURED_COMPONENT_H
 
-#include <stdint.h>
-#include <sys/types.h>
-#include <stdlib.h>
-
-#include "RenderScript.h"
+#include "rsUtils.h"
 #include "rsObjectBase.h"
 
 // ---------------------------------------------------------------------------
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 455c18d..4025ff8 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -20,6 +20,9 @@
 #include "utils/String8.h"
 #include <ui/FramebufferNativeWindow.h>
 
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
 using namespace android;
 using namespace android::renderscript;
 
@@ -116,9 +119,6 @@
      Context *rsc = static_cast<Context *>(vrsc);
 
      gIO = new ThreadIO();
-     rsc->mServerCommands.init(128);
-     rsc->mServerReturns.init(128);
-
      rsc->initEGL();
 
      ScriptTLSStruct *tlsStruct = new ScriptTLSStruct;
@@ -166,9 +166,6 @@
     mRunning = false;
     mExit = false;
 
-    mServerCommands.init(256);
-    mServerReturns.init(256);
-
     // see comment in header
     gCon = this;
 
@@ -191,13 +188,14 @@
     sparam.sched_priority = ANDROID_PRIORITY_DISPLAY;
     pthread_attr_setschedparam(&threadAttr, &sparam);
 
-    LOGE("RS Launching thread");
+    mWndSurface = sur;
+
+    LOGV("RS Launching thread");
     status = pthread_create(&mThreadId, &threadAttr, threadProc, this);
     if (status) {
         LOGE("Failed to start rs context thread.");
     }
 
-    mWndSurface = sur;
     while(!mRunning) {
         sleep(1);
     }
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index e9d75e0..4d96a77 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -32,6 +32,7 @@
 #include "rsProgramFragment.h"
 #include "rsProgramFragmentStore.h"
 #include "rsProgramVertex.h"
+#include "rsLight.h"
 
 #include "rsgApiStructs.h"
 #include "rsLocklessFifo.h"
@@ -61,6 +62,7 @@
     ProgramFragmentState mStateFragment;
     ProgramFragmentStoreState mStateFragmentStore;
     ProgramVertexState mStateVertex;
+    LightState mStateLight;
 
     TriangleMeshContext mStateTriangleMesh;
 
@@ -113,9 +115,6 @@
     bool mRunning;
     bool mExit;
 
-    LocklessCommandFifo mServerCommands;
-    LocklessCommandFifo mServerReturns;
-
     pthread_t mThreadId;
 
     ObjectBaseRef<Script> mRootScript;
diff --git a/libs/rs/rsDevice.h b/libs/rs/rsDevice.h
index 3de3ffa..156315f 100644
--- a/libs/rs/rsDevice.h
+++ b/libs/rs/rsDevice.h
@@ -17,9 +17,7 @@
 #ifndef ANDROID_RS_DEVICE_H
 #define ANDROID_RS_DEVICE_H
 
-#include <utils/Vector.h>
-
-//#include "StructuredComponent.h"
+#include "rsUtils.h"
 
 // ---------------------------------------------------------------------------
 namespace android {
diff --git a/libs/rs/rsElement.cpp b/libs/rs/rsElement.cpp
index 5a44f47..069a128 100644
--- a/libs/rs/rsElement.cpp
+++ b/libs/rs/rsElement.cpp
@@ -410,8 +410,6 @@
 
     rsc->mStateElement.mComponentBuildList.clear();
     se->incRef();
-
-    LOGE("Create %p", se);
     return se;
 }
 
diff --git a/libs/rs/rsElement.h b/libs/rs/rsElement.h
index 2434977..ea6fa8f 100644
--- a/libs/rs/rsElement.h
+++ b/libs/rs/rsElement.h
@@ -17,8 +17,6 @@
 #ifndef ANDROID_STRUCTURED_ELEMENT_H
 #define ANDROID_STRUCTURED_ELEMENT_H
 
-#include <utils/Vector.h>
-
 #include "rsComponent.h"
 
 // ---------------------------------------------------------------------------
diff --git a/libs/rs/rsLight.cpp b/libs/rs/rsLight.cpp
new file mode 100644
index 0000000..67d0095
--- /dev/null
+++ b/libs/rs/rsLight.cpp
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ */
+
+#include "rsContext.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+
+Light::Light(bool isLocal, bool isMono)
+{
+    mIsLocal = isLocal;
+    mIsMono = isMono;
+
+    mX = 0;
+    mY = 0;
+    mZ = 0;
+
+    mR = 1.f;
+    mG = 1.f;
+    mB = 1.f;
+}
+
+Light::~Light()
+{
+}
+
+void Light::setPosition(float x, float y, float z)
+{
+    mX = x;
+    mY = y;
+    mZ = z;
+}
+
+void Light::setColor(float r, float g, float b)
+{
+    mR = r;
+    mG = g;
+    mB = b;
+}
+
+////////////////////////////////////////////
+
+LightState::LightState()
+{
+    clear();
+}
+
+LightState::~LightState()
+{
+}
+
+void LightState::clear()
+{
+    mIsLocal = false;
+    mIsMono = false;
+}
+
+
+////////////////////////////////////////////////////
+// 
+
+namespace android {
+namespace renderscript {
+
+void rsi_LightBegin(Context *rsc)
+{
+    rsc->mStateLight.clear();
+}
+
+void rsi_LightSetLocal(Context *rsc, bool isLocal)
+{
+    rsc->mStateLight.mIsLocal = isLocal;
+}
+
+void rsi_LightSetMonochromatic(Context *rsc, bool isMono)
+{
+    rsc->mStateLight.mIsMono = isMono;
+}
+
+RsLight rsi_LightCreate(Context *rsc)
+{
+    Light *l = new Light(rsc->mStateLight.mIsLocal,
+                         rsc->mStateLight.mIsMono);
+    l->incRef();
+    return l;
+}
+
+void rsi_LightDestroy(Context *rsc, RsLight vl)
+{
+    Light *l = static_cast<Light *>(vl);
+    l->decRef();
+}
+
+void rsi_LightSetColor(Context *rsc, RsLight vl, float r, float g, float b)
+{
+    Light *l = static_cast<Light *>(vl);
+    l->setColor(r, g, b);
+}
+
+void rsi_LightSetPosition(Context *rsc, RsLight vl, float x, float y, float z)
+{
+    Light *l = static_cast<Light *>(vl);
+    l->setPosition(x, y, z);
+}
+
+
+
+}
+}
diff --git a/libs/rs/rsLight.h b/libs/rs/rsLight.h
new file mode 100644
index 0000000..76d1ecc
--- /dev/null
+++ b/libs/rs/rsLight.h
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_LIGHT_H
+#define ANDROID_LIGHT_H
+
+
+#include "rsObjectBase.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+
+// An element is a group of Components that occupies one cell in a structure.
+class Light : public ObjectBase
+{
+public:
+    Light(bool isLocal, bool isMono);
+    virtual ~Light();
+
+    // Values, mutable after creation.
+    void setPosition(float x, float y, float z);
+    void setColor(float r, float g, float b);
+
+protected:
+    float mR, mG, mB;
+    float mX, mY, mZ;
+    bool mIsLocal;
+    bool mIsMono;
+};
+
+
+class LightState {
+public:
+    LightState();
+    ~LightState();
+
+    void clear();
+
+    bool mIsMono;
+    bool mIsLocal;
+};
+
+
+}
+}
+#endif //ANDROID_LIGHT_H
+
diff --git a/libs/rs/rsLocklessFifo.cpp b/libs/rs/rsLocklessFifo.cpp
index 37ec14b..c3fee54 100644
--- a/libs/rs/rsLocklessFifo.cpp
+++ b/libs/rs/rsLocklessFifo.cpp
@@ -18,7 +18,6 @@
 
 using namespace android;
 
-#include <utils/Log.h>
 
 LocklessCommandFifo::LocklessCommandFifo()
 {
@@ -65,8 +64,6 @@
     if (freeSpace < 0) {
         freeSpace = 0;
     }
-    
-    //LOGE("free %i", freeSpace);
     return freeSpace;
 }
 
@@ -91,13 +88,11 @@
 
 void LocklessCommandFifo::commit(uint32_t command, uint32_t sizeInBytes)
 {
-    //LOGE("commit cmd %i  size %i", command, sizeInBytes);
     //dumpState("commit 1");
     reinterpret_cast<uint16_t *>(mPut)[0] = command;
     reinterpret_cast<uint16_t *>(mPut)[1] = sizeInBytes;
     mPut += ((sizeInBytes + 3) & ~3) + 4;
     //dumpState("commit 2");
-
     mSignalToWorker.set();
 }
 
@@ -124,12 +119,9 @@
             mSignalToControl.set();
             mSignalToWorker.wait();
         }
-        //dumpState("get 3");
 
         *command = reinterpret_cast<const uint16_t *>(mGet)[0];
         *bytesData = reinterpret_cast<const uint16_t *>(mGet)[1];
-        //LOGE("Got %i, %i", *command, *bytesData);
-    
         if (*command) {
             // non-zero command is valid
             return mGet+4;
@@ -174,7 +166,7 @@
 
 void LocklessCommandFifo::dumpState(const char *s) const
 {
-    LOGE("%s  put %p, get %p,  buf %p,  end %p", s, mPut, mGet, mBuffer, mEnd);
+    LOGV("%s  put %p, get %p,  buf %p,  end %p", s, mPut, mGet, mBuffer, mEnd);
 }
 
 LocklessCommandFifo::Signal::Signal()
diff --git a/libs/rs/rsLocklessFifo.h b/libs/rs/rsLocklessFifo.h
index 2f4d5c5..abeddf7 100644
--- a/libs/rs/rsLocklessFifo.h
+++ b/libs/rs/rsLocklessFifo.h
@@ -18,10 +18,7 @@
 #define ANDROID_RS_LOCKLESS_FIFO_H
 
 
-#include <stdint.h>
-#include <sys/types.h>
-#include <stdlib.h>
-#include <pthread.h>
+#include "rsUtils.h"
 
 namespace android {
 
diff --git a/libs/rs/rsMatrix.cpp b/libs/rs/rsMatrix.cpp
index 258b836..5f68197 100644
--- a/libs/rs/rsMatrix.cpp
+++ b/libs/rs/rsMatrix.cpp
@@ -20,8 +20,6 @@
 #include "string.h"
 #include "math.h"
 
-#include <utils/Log.h>
-
 using namespace android;
 using namespace android::renderscript;
 
diff --git a/libs/rs/rsObjectBase.cpp b/libs/rs/rsObjectBase.cpp
index 8f5232a..3219c39 100644
--- a/libs/rs/rsObjectBase.cpp
+++ b/libs/rs/rsObjectBase.cpp
@@ -15,7 +15,6 @@
  */
 
 #include "rsObjectBase.h"
-#include <utils/Log.h>
 
 using namespace android;
 using namespace android::renderscript;
@@ -34,14 +33,14 @@
 void ObjectBase::incRef() const
 {
     mRefCount ++;
-    //LOGE("ObjectBase %p inc ref %i", this, mRefCount);
+    //LOGV("ObjectBase %p inc ref %i", this, mRefCount);
 }
 
 void ObjectBase::decRef() const
 {
     rsAssert(mRefCount > 0);
     mRefCount --;
-    //LOGE("ObjectBase %p dec ref %i", this, mRefCount);
+    //LOGV("ObjectBase %p dec ref %i", this, mRefCount);
     if (!mRefCount) {
         delete this;
     }
diff --git a/libs/rs/rsProgramFragment.cpp b/libs/rs/rsProgramFragment.cpp
index 8777335..f2e7095 100644
--- a/libs/rs/rsProgramFragment.cpp
+++ b/libs/rs/rsProgramFragment.cpp
@@ -17,6 +17,9 @@
 #include "rsContext.h"
 #include "rsProgramFragment.h"
 
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
 using namespace android;
 using namespace android::renderscript;
 
@@ -168,8 +171,6 @@
 {
     ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
     pf->bindTexture(slot, static_cast<Allocation *>(a));
-
-    //LOGE("%p %p", pf, rsc->getFragment());
     if (pf == rsc->getFragment()) {
         pf->setupGL();
     }
diff --git a/libs/rs/rsProgramFragmentStore.cpp b/libs/rs/rsProgramFragmentStore.cpp
index 96d37ae..0b65680 100644
--- a/libs/rs/rsProgramFragmentStore.cpp
+++ b/libs/rs/rsProgramFragmentStore.cpp
@@ -17,6 +17,9 @@
 #include "rsContext.h"
 #include "rsProgramFragmentStore.h"
 
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
 using namespace android;
 using namespace android::renderscript;
 
diff --git a/libs/rs/rsProgramVertex.cpp b/libs/rs/rsProgramVertex.cpp
index 19afad5..4089507 100644
--- a/libs/rs/rsProgramVertex.cpp
+++ b/libs/rs/rsProgramVertex.cpp
@@ -17,6 +17,9 @@
 #include "rsContext.h"
 #include "rsProgramVertex.h"
 
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
 using namespace android;
 using namespace android::renderscript;
 
@@ -33,11 +36,11 @@
 
 static void logMatrix(const char *txt, const float *f)
 {
-    LOGE("Matrix %s, %p", txt, f);
-    LOGE("%6.2f, %6.2f, %6.2f, %6.2f", f[0], f[4], f[8], f[12]);
-    LOGE("%6.2f, %6.2f, %6.2f, %6.2f", f[1], f[5], f[9], f[13]);
-    LOGE("%6.2f, %6.2f, %6.2f, %6.2f", f[2], f[6], f[10], f[14]);
-    LOGE("%6.2f, %6.2f, %6.2f, %6.2f", f[3], f[7], f[11], f[15]);
+    LOGV("Matrix %s, %p", txt, f);
+    LOGV("%6.2f, %6.2f, %6.2f, %6.2f", f[0], f[4], f[8], f[12]);
+    LOGV("%6.2f, %6.2f, %6.2f, %6.2f", f[1], f[5], f[9], f[13]);
+    LOGV("%6.2f, %6.2f, %6.2f, %6.2f", f[2], f[6], f[10], f[14]);
+    LOGV("%6.2f, %6.2f, %6.2f, %6.2f", f[3], f[7], f[11], f[15]);
 }
 
 void ProgramVertex::setupGL()
diff --git a/libs/rs/rsSampler.cpp b/libs/rs/rsSampler.cpp
index d89346e..418f127 100644
--- a/libs/rs/rsSampler.cpp
+++ b/libs/rs/rsSampler.cpp
@@ -14,16 +14,13 @@
  * limitations under the License.
  */
 
-#include "rsContext.h"
-
-
 #include <GLES/gl.h>
 #include <GLES/glext.h>
-#include <utils/Log.h>
 
 #include "rsContext.h"
 #include "rsSampler.h"
 
+
 using namespace android;
 using namespace android::renderscript;
 
diff --git a/libs/rs/rsSampler.h b/libs/rs/rsSampler.h
index 45d8c61..4b504f6 100644
--- a/libs/rs/rsSampler.h
+++ b/libs/rs/rsSampler.h
@@ -17,11 +17,6 @@
 #ifndef ANDROID_RS_SAMPLER_H
 #define ANDROID_RS_SAMPLER_H
 
-#include <math.h>
-#include <EGL/egl.h>
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-
 #include "rsAllocation.h"
 #include "RenderScript.h"
 
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index e170b8c..522ed00 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -21,6 +21,9 @@
 #include "acc/acc.h"
 #include "utils/String8.h"
 
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
 using namespace android;
 using namespace android::renderscript;
 
@@ -469,14 +472,10 @@
         accGetPragmas(mAccScript, &pragmaCount, pragmaMax, &str[0]);
 
         for (int ct=0; ct < pragmaCount; ct+=2) {
-            LOGE("pragma %i %s %s", ct, str[ct], str[ct+1]);
-
             if (!strcmp(str[ct], "version")) {
                 continue;
-
             }
 
-
             if (!strcmp(str[ct], "stateVertex")) {
                 if (!strcmp(str[ct+1], "default")) {
                     continue;
diff --git a/libs/rs/rsThreadIO.cpp b/libs/rs/rsThreadIO.cpp
index 5641581..89df59d 100644
--- a/libs/rs/rsThreadIO.cpp
+++ b/libs/rs/rsThreadIO.cpp
@@ -16,8 +16,6 @@
 
 #include "rsContext.h"
 
-#include <utils/Log.h>
-
 #include "rsThreadIO.h"
 
 using namespace android;
@@ -36,22 +34,17 @@
 
 bool ThreadIO::playCoreCommands(Context *con, bool waitForCommand)
 {
-    //LOGE("playCoreCommands 1");
     uint32_t cmdID = 0;
     uint32_t cmdSize = 0;
     bool ret = false;
     while(!mToCore.isEmpty() || waitForCommand) {
         ret = true;
-        //LOGE("playCoreCommands 2");
         const void * data = mToCore.get(&cmdID, &cmdSize);
         waitForCommand = false;
-        //LOGE("playCoreCommands 3 %i %i", cmdID, cmdSize);
+        //LOGV("playCoreCommands 3 %i %i", cmdID, cmdSize);
 
         gPlaybackFuncs[cmdID](con, data);
-        //LOGE("playCoreCommands 4");
-
         mToCore.next();
-        //LOGE("playCoreCommands 5");
     }
     return ret;
 }
diff --git a/libs/rs/rsThreadIO.h b/libs/rs/rsThreadIO.h
index 973ee05..72746c5 100644
--- a/libs/rs/rsThreadIO.h
+++ b/libs/rs/rsThreadIO.h
@@ -17,11 +17,7 @@
 #ifndef ANDROID_RS_THREAD_IO_H
 #define ANDROID_RS_THREAD_IO_H
 
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "RenderScript.h"
-
+#include "rsUtils.h"
 #include "rsLocklessFifo.h"
 
 // ---------------------------------------------------------------------------
diff --git a/libs/rs/rsTriangleMesh.cpp b/libs/rs/rsTriangleMesh.cpp
index 6595ebc..8c7bc92 100644
--- a/libs/rs/rsTriangleMesh.cpp
+++ b/libs/rs/rsTriangleMesh.cpp
@@ -22,8 +22,6 @@
 #include <GLES/gl.h>
 #include <GLES/glext.h>
 
-#include <utils/Log.h>
-
 TriangleMesh::TriangleMesh()
 {
     mVertexElement = NULL;
@@ -122,7 +120,7 @@
             mSizeTex = 2;
         }
     }
-    LOGE("TriangleMesh %i,%i  %i,%i  %i,%i", mSizeCoord, mOffsetCoord, mSizeNorm, mOffsetNorm, mSizeTex, mOffsetTex);
+    LOGV("TriangleMesh %i,%i  %i,%i  %i,%i", mSizeCoord, mOffsetCoord, mSizeNorm, mOffsetNorm, mSizeTex, mOffsetTex);
 
 }
 
@@ -132,7 +130,6 @@
 
 void rsi_TriangleMeshBegin(Context *rsc, RsElement vertex, RsElement index)
 {
-    //LOGE("tmb  %p %p", vertex, index);
     TriangleMeshContext *tmc = &rsc->mStateTriangleMesh;
 
     tmc->clear();
@@ -141,8 +138,6 @@
     tmc->mIndexElement = static_cast<Element *>(index);
     tmc->mIndexSizeBits = tmc->mIndexElement->getSizeBits();
 
-    //LOGE("Element sizes  %i  %i", tmc->mVertexSizeBits, tmc->mIndexSizeBits);
-
     assert(!(tmc->mVertexSizeBits & 0x7));
     assert(!(tmc->mIndexSizeBits & 0x7));
 }
@@ -200,8 +195,6 @@
         return 0;
     }
 
-    LOGE("Create mesh, triangleCount %i", tm->mTriangleCount);
-
     memcpy(tm->mVertexData, tmc->mVertexData.array(), tm->mVertexDataSize);
     memcpy(tm->mIndexData, tmc->mIndexData.array(), tm->mIndexDataSize);
     tm->analyzeElement();
@@ -227,8 +220,6 @@
 
     rsc->setupCheck();
 
-    //LOGE("1  %p   ", vtm);
-    //LOGE("1.1  %p   %p", tm->mVertexData,  tm->mIndexData);
     if (!tm->mBufferObjects[0]) {
         glGenBuffers(2, &tm->mBufferObjects[0]);
 
@@ -241,7 +232,6 @@
         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
     }
 
-    //LOGE("1.2");
     if (first >= tm->mTriangleCount) {
         return;
     }
@@ -254,7 +244,6 @@
 
     const float *f = (const float *)tm->mVertexData;
 
-    //LOGE("2");
     glBindBuffer(GL_ARRAY_BUFFER, tm->mBufferObjects[0]);
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tm->mBufferObjects[1]);
 
@@ -285,8 +274,6 @@
 
     glDrawElements(GL_TRIANGLES, count * 3, GL_UNSIGNED_SHORT, (GLvoid *)(first * 3 * 2));
 
-    //LOGE("4");
-
     glBindBuffer(GL_ARRAY_BUFFER, 0);
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
 }
diff --git a/libs/rs/rsTriangleMesh.h b/libs/rs/rsTriangleMesh.h
index 4e15d5a..e56c7c2 100644
--- a/libs/rs/rsTriangleMesh.h
+++ b/libs/rs/rsTriangleMesh.h
@@ -17,15 +17,6 @@
 #ifndef ANDROID_RS_TRIANGLE_MESH_H
 #define ANDROID_RS_TRIANGLE_MESH_H
 
-#include <stdlib.h>
-#include <stdio.h>
-
-#include <math.h>
-#include <EGL/egl.h>
-#include <GLES/gl.h>
-#include <GLES/glext.h>
-
-#include <utils/Vector.h>
 
 #include "RenderScript.h"
 
@@ -60,7 +51,7 @@
     size_t mSizeNorm;
 
     // GL buffer info
-    GLuint mBufferObjects[2];
+    uint32_t mBufferObjects[2];
 
     void analyzeElement();
 protected:
diff --git a/libs/rs/rsType.cpp b/libs/rs/rsType.cpp
index 6b99820..bbe9720 100644
--- a/libs/rs/rsType.cpp
+++ b/libs/rs/rsType.cpp
@@ -63,7 +63,6 @@
 
 void Type::compute()
 {
-    //LOGE("compute");
     uint32_t oldLODCount = mLODCount;
     if (mDimLOD) {
         uint32_t l2x = rsFindHighBit(mDimX) + 1;
@@ -80,9 +79,6 @@
         mLODs = new LOD[mLODCount];
     }
 
-    //LOGE("xyz %i %i %i", mDimX, mDimY, mDimZ);
-    //LOGE("mips %i", mLODCount);
-    //LOGE("e size %i", mElement->getSizeBytes());
     uint32_t tx = mDimX;
     uint32_t ty = mDimY;
     uint32_t tz = mDimZ;
@@ -92,15 +88,12 @@
         mLODs[lod].mY = ty;
         mLODs[lod].mZ = tz;
         mLODs[lod].mOffset = offset;
-        //LOGE("txyz %i %i %i", tx, ty, tz);
         offset += tx * rsMax(ty, 1u) * rsMax(tz, 1u) * mElement->getSizeBytes();
-        tx >>= 1;
-        ty >>= 1;
-        tz >>= 1;
+        tx = (tx + 1) >> 1;
+        ty = (ty + 1) >> 1;
+        tz = (tz + 1) >> 1;
     }
 
-    //LOGE("size %i", offset);
-
     // At this point the offset is the size of a mipmap chain;
     mMipChainSizeBytes = offset;
 
diff --git a/libs/rs/rsUtils.h b/libs/rs/rsUtils.h
index 5a43fb3..3d3437b 100644
--- a/libs/rs/rsUtils.h
+++ b/libs/rs/rsUtils.h
@@ -17,9 +17,14 @@
 #ifndef ANDROID_RS_UTILS_H
 #define ANDROID_RS_UTILS_H
 
-#include <stdint.h>
-#include <sys/types.h>
+#define LOG_NDEBUG 0 
+#define LOG_TAG "rs"
+#include <utils/Log.h>
+#include <utils/Vector.h>
 #include <stdlib.h>
+#include <pthread.h>
+
+#include "RenderScript.h"
 
 namespace android {
 namespace renderscript {
diff --git a/libs/ui/Camera.cpp b/libs/ui/Camera.cpp
index 4228300..33b99b9 100644
--- a/libs/ui/Camera.cpp
+++ b/libs/ui/Camera.cpp
@@ -85,20 +85,6 @@
 void Camera::init()
 {
     mStatus = UNKNOWN_ERROR;
-    mShutterCallback = 0;
-    mShutterCallbackCookie = 0;
-    mRawCallback = 0;
-    mRawCallbackCookie = 0;
-    mJpegCallback = 0;
-    mJpegCallbackCookie = 0;
-    mPreviewCallback = 0;
-    mPreviewCallbackCookie = 0;
-    mRecordingCallback = 0;
-    mRecordingCallbackCookie = 0;
-    mErrorCallback = 0;
-    mErrorCallbackCookie = 0;
-    mAutoFocusCallback = 0;
-    mAutoFocusCallbackCookie = 0;
 }
 
 Camera::~Camera()
@@ -127,7 +113,6 @@
 {
     LOGV("disconnect");
     if (mCamera != 0) {
-        mErrorCallback = 0;
         mCamera->disconnect();
         mCamera = 0;
     }
@@ -285,125 +270,49 @@
     return params;
 }
 
-void Camera::setAutoFocusCallback(autofocus_callback cb, void *cookie)
+void Camera::setListener(const sp<CameraListener>& listener)
 {
-    LOGV("setAutoFocusCallback");
-    mAutoFocusCallback = cb;
-    mAutoFocusCallbackCookie = cookie;
+    Mutex::Autolock _l(mLock);
+    mListener = listener;
 }
 
-void Camera::setShutterCallback(shutter_callback cb, void *cookie)
+void Camera::setPreviewCallbackFlags(int flag)
 {
-    LOGV("setShutterCallback");
-    mShutterCallback = cb;
-    mShutterCallbackCookie = cookie;
-}
-
-void Camera::setRawCallback(frame_callback cb, void *cookie)
-{
-    LOGV("setRawCallback");
-    mRawCallback = cb;
-    mRawCallbackCookie = cookie;
-}
-
-void Camera::setJpegCallback(frame_callback cb, void *cookie)
-{
-    LOGV("setJpegCallback");
-    mJpegCallback = cb;
-    mJpegCallbackCookie = cookie;
-}
-
-void Camera::setPreviewCallback(frame_callback cb, void *cookie, int flag)
-{
-    LOGV("setPreviewCallback");
-    mPreviewCallback = cb;
-    mPreviewCallbackCookie = cookie;
+    LOGV("setPreviewCallbackFlags");
     sp <ICamera> c = mCamera;
     if (c == 0) return;
     mCamera->setPreviewCallbackFlag(flag);
 }
 
-void Camera::setRecordingCallback(frame_callback cb, void *cookie)
-{
-    LOGV("setRecordingCallback");
-    mRecordingCallback = cb;
-    mRecordingCallbackCookie = cookie;
-}
-
-void Camera::setErrorCallback(error_callback cb, void *cookie)
-{
-    LOGV("setErrorCallback");
-    mErrorCallback = cb;
-    mErrorCallbackCookie = cookie;
-}
-
 // callback from camera service
 void Camera::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2)
 {
-    switch(msgType) {
-    case CAMERA_MSG_ERROR:
-        LOGV("errorCallback");
-        if (mErrorCallback) {
-            mErrorCallback((status_t)ext1, mErrorCallbackCookie);
-        }
-        break;
-    case CAMERA_MSG_FOCUS:
-        LOGV("autoFocusCallback");
-        if (mAutoFocusCallback) {
-            mAutoFocusCallback((bool)ext1, mAutoFocusCallbackCookie);
-        }
-        break;
-    case CAMERA_MSG_SHUTTER:
-        LOGV("shutterCallback");
-        if (mShutterCallback) {
-            mShutterCallback(mShutterCallbackCookie);
-        }
-        break;
-    default:
-        LOGV("notifyCallback(%d, %d, %d)", msgType, ext1, ext2);
-        break;
+    sp<CameraListener> listener;
+    {
+        Mutex::Autolock _l(mLock);
+        listener = mListener;
+    }
+    if (listener != NULL) {
+        listener->notify(msgType, ext1, ext2);
     }
 }
 
 // callback from camera service when frame or image is ready
 void Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr)
 {
-    switch(msgType) {
-    case CAMERA_MSG_PREVIEW_FRAME:
-        LOGV("previewCallback");
-        if (mPreviewCallback) {
-            mPreviewCallback(dataPtr, mPreviewCallbackCookie);
-        }
-        break;
-    case CAMERA_MSG_VIDEO_FRAME:
-        LOGV("recordingCallback");
-        if (mRecordingCallback) {
-            mRecordingCallback(dataPtr, mRecordingCallbackCookie);
-        }
-        break;
-    case CAMERA_MSG_RAW_IMAGE:
-        LOGV("rawCallback");
-        if (mRawCallback) {
-            mRawCallback(dataPtr, mRawCallbackCookie);
-        }
-        break;
-    case CAMERA_MSG_COMPRESSED_IMAGE:
-        LOGV("jpegCallback");
-        if (mJpegCallback) {
-            mJpegCallback(dataPtr, mJpegCallbackCookie);
-        }
-        break;
-    default:
-        LOGV("dataCallback(%d, %p)", msgType, dataPtr.get());
-        break;
+    sp<CameraListener> listener;
+    {
+        Mutex::Autolock _l(mLock);
+        listener = mListener;
+    }
+    if (listener != NULL) {
+        listener->postData(msgType, dataPtr);
     }
 }
 
 void Camera::binderDied(const wp<IBinder>& who) {
     LOGW("ICamera died");
-    if (mErrorCallback) {
-        mErrorCallback(DEAD_OBJECT, mErrorCallbackCookie);
-    }
+    notifyCallback(CAMERA_MSG_ERROR, DEAD_OBJECT, 0);
 }
 
 void Camera::DeathNotifier::binderDied(const wp<IBinder>& who) {
diff --git a/libs/utils/BackupData.cpp b/libs/utils/BackupData.cpp
index 6a7f056..0868cff 100644
--- a/libs/utils/BackupData.cpp
+++ b/libs/utils/BackupData.cpp
@@ -99,10 +99,20 @@
         return amt;
     }
 
+    String8 k;
+    if (m_keyPrefix.length() > 0) {
+        k = m_keyPrefix;
+        k += ":";
+        k += key;
+    } else {
+        k = key;
+    }
+    LOGD("m_keyPrefix=%s key=%s k=%s", m_keyPrefix.string(), key.string(), k.string());
+
     entity_header_v1 header;
     ssize_t keyLen;
 
-    keyLen = key.length();
+    keyLen = k.length();
 
     header.type = tolel(BACKUP_HEADER_ENTITY_V1);
     header.keyLen = tolel(keyLen);
@@ -115,7 +125,7 @@
     }
     m_pos += amt;
 
-    amt = write(m_fd, key.string(), keyLen+1);
+    amt = write(m_fd, k.string(), keyLen+1);
     if (amt != keyLen+1) {
         m_status = errno;
         return m_status;
@@ -148,6 +158,11 @@
     return NO_ERROR;
 }
 
+void
+BackupDataWriter::SetKeyPrefix(const String8& keyPrefix)
+{
+    m_keyPrefix = keyPrefix;
+}
 
 
 BackupDataReader::BackupDataReader(int fd)
@@ -298,7 +313,7 @@
     if (remaining <= 0) {
         return 0;
     }
-    if (size > remaining) {
+    if (((int)size) > remaining) {
         size = remaining;
     }
     //LOGD("   reading %d bytes", size);
diff --git a/libs/utils/BackupHelpers.cpp b/libs/utils/BackupHelpers.cpp
index d65a457..99a4abc 100644
--- a/libs/utils/BackupHelpers.cpp
+++ b/libs/utils/BackupHelpers.cpp
@@ -41,6 +41,33 @@
 #define MAGIC0 0x70616e53 // Snap
 #define MAGIC1 0x656c6946 // File
 
+/*
+ * File entity data format (v1):
+ *
+ *   - 4-byte version number of the metadata, little endian (0x00000001 for v1)
+ *   - 12 bytes of metadata
+ *   - the file data itself
+ *
+ * i.e. a 16-byte metadata header followed by the raw file data.  If the
+ * restore code does not recognize the metadata version, it can still
+ * interpret the file data itself correctly.
+ *
+ * file_metadata_v1:
+ *
+ *   - 4 byte version number === 0x00000001 (little endian)
+ *   - 4-byte access mode (little-endian)
+ *   - undefined (8 bytes)
+ */
+
+struct file_metadata_v1 {
+    int version;
+    int mode;
+    int undefined_1;
+    int undefined_2;
+};
+
+const static int CURRENT_METADATA_VERSION = 1;
+
 #if 1 // TEST_BACKUP_HELPERS
 #define LOGP(f, x...) printf(f "\n", x)
 #else
@@ -181,29 +208,48 @@
 }
 
 static int
-write_update_file(BackupDataWriter* dataStream, int fd, const String8& key,
+write_update_file(BackupDataWriter* dataStream, int fd, int mode, const String8& key,
         char const* realFilename)
 {
-    LOGP("write_update_file %s (%s)\n", realFilename, key.string());
+    LOGP("write_update_file %s (%s) : mode 0%o\n", realFilename, key.string(), mode);
 
     const int bufsize = 4*1024;
     int err;
     int amt;
     int fileSize;
     int bytesLeft;
+    file_metadata_v1 metadata;
 
     char* buf = (char*)malloc(bufsize);
     int crc = crc32(0L, Z_NULL, 0);
 
 
-    bytesLeft = fileSize = lseek(fd, 0, SEEK_END);
+    fileSize = lseek(fd, 0, SEEK_END);
     lseek(fd, 0, SEEK_SET);
 
+    if (sizeof(metadata) != 16) {
+        LOGE("ERROR: metadata block is the wrong size!");
+    }
+
+    bytesLeft = fileSize + sizeof(metadata);
     err = dataStream->WriteEntityHeader(key, bytesLeft);
     if (err != 0) {
+        free(buf);
         return err;
     }
 
+    // store the file metadata first
+    metadata.version = tolel(CURRENT_METADATA_VERSION);
+    metadata.mode = tolel(mode);
+    metadata.undefined_1 = metadata.undefined_2 = 0;
+    err = dataStream->WriteEntityData(&metadata, sizeof(metadata));
+    if (err != 0) {
+        free(buf);
+        return err;
+    }
+    bytesLeft -= sizeof(metadata); // bytesLeft should == fileSize now
+
+    // now store the file content
     while ((amt = read(fd, buf, bufsize)) != 0 && bytesLeft > 0) {
         bytesLeft -= amt;
         if (bytesLeft < 0) {
@@ -211,6 +257,7 @@
         }
         err = dataStream->WriteEntityData(buf, amt);
         if (err != 0) {
+            free(buf);
             return err;
         }
     }
@@ -224,6 +271,7 @@
                 bytesLeft -= amt;
                 err = dataStream->WriteEntityData(buf, amt);
                 if (err != 0) {
+                    free(buf);
                     return err;
                 }
             }
@@ -233,7 +281,6 @@
     }
 
     free(buf);
-
     return NO_ERROR;
 }
 
@@ -241,11 +288,19 @@
 write_update_file(BackupDataWriter* dataStream, const String8& key, char const* realFilename)
 {
     int err;
+    struct stat st;
+
+    err = stat(realFilename, &st);
+    if (err < 0) {
+        return errno;
+    }
+
     int fd = open(realFilename, O_RDONLY);
     if (fd == -1) {
         return errno;
     }
-    err = write_update_file(dataStream, fd, key, realFilename);
+
+    err = write_update_file(dataStream, fd, st.st_mode, key, realFilename);
     close(fd);
     return err;
 }
@@ -266,7 +321,6 @@
     }
 
     free(buf);
-
     return crc;
 }
 
@@ -302,6 +356,7 @@
             r.s.modTime_sec = st.st_mtime;
             r.s.modTime_nsec = 0; // workaround sim breakage
             //r.s.modTime_nsec = st.st_mtime_nsec;
+            r.s.mode = st.st_mode;
             r.s.size = st.st_size;
             // we compute the crc32 later down below, when we already have the file open.
 
@@ -349,13 +404,13 @@
                 g.s.crc32 = compute_crc32(fd);
 
                 LOGP("%s", q.string());
-                LOGP("  new: modTime=%d,%d size=%-3d crc32=0x%08x",
-                        f.modTime_sec, f.modTime_nsec, f.size, f.crc32);
-                LOGP("  old: modTime=%d,%d size=%-3d crc32=0x%08x",
-                        g.s.modTime_sec, g.s.modTime_nsec, g.s.size, g.s.crc32);
+                LOGP("  new: modTime=%d,%d mode=%04o size=%-3d crc32=0x%08x",
+                        f.modTime_sec, f.modTime_nsec, f.mode, f.size, f.crc32);
+                LOGP("  old: modTime=%d,%d mode=%04o size=%-3d crc32=0x%08x",
+                        g.s.modTime_sec, g.s.modTime_nsec, g.s.mode, g.s.size, g.s.crc32);
                 if (f.modTime_sec != g.s.modTime_sec || f.modTime_nsec != g.s.modTime_nsec
-                        || f.size != g.s.size || f.crc32 != g.s.crc32) {
-                    write_update_file(dataStream, fd, p, g.file.string());
+                        || f.mode != g.s.mode || f.size != g.s.size || f.crc32 != g.s.crc32) {
+                    write_update_file(dataStream, fd, g.s.mode, p, g.file.string());
                 }
 
                 close(fd);
@@ -389,6 +444,7 @@
 RestoreHelperBase::RestoreHelperBase()
 {
     m_buf = malloc(RESTORE_BUF_SIZE);
+    m_loggedUnknownMetadata = false;
 }
 
 RestoreHelperBase::~RestoreHelperBase()
@@ -415,8 +471,25 @@
         return err;
     }
 
-    // TODO: World readable/writable for now.
-    mode = 0666;
+    // Get the metadata block off the head of the file entity and use that to
+    // set up the output file
+    file_metadata_v1 metadata;
+    amt = in->ReadEntityData(&metadata, sizeof(metadata));
+    if (amt != sizeof(metadata)) {
+        LOGW("Could not read metadata for %s -- %ld / %s", filename.string(),
+                (long)amt, strerror(errno));
+        return EIO;
+    }
+    metadata.version = fromlel(metadata.version);
+    metadata.mode = fromlel(metadata.mode);
+    if (metadata.version > CURRENT_METADATA_VERSION) {
+        if (!m_loggedUnknownMetadata) {
+            m_loggedUnknownMetadata = true;
+            LOGW("Restoring file with unsupported metadata version %d (currently %d)",
+                    metadata.version, CURRENT_METADATA_VERSION);
+        }
+    }
+    mode = metadata.mode;
 
     // Write the file and compute the crc
     crc = crc32(0L, Z_NULL, 0);
@@ -450,6 +523,7 @@
     r.s.modTime_sec = st.st_mtime;
     r.s.modTime_nsec = 0; // workaround sim breakage
     //r.s.modTime_nsec = st.st_mtime_nsec;
+    r.s.mode = st.st_mode;
     r.s.size = st.st_size;
     r.s.crc32 = crc;
 
@@ -536,6 +610,7 @@
         }
     }
 
+    free(contents);
     return contentsMatch && sizesMatch ? 0 : 1;
 }
 
@@ -623,6 +698,7 @@
 
     states[0].modTime_sec = 0xfedcba98;
     states[0].modTime_nsec = 0xdeadbeef;
+    states[0].mode = 0777; // decimal 511, hex 0x000001ff
     states[0].size = 0xababbcbc;
     states[0].crc32 = 0x12345678;
     states[0].nameLen = -12;
@@ -632,6 +708,7 @@
 
     states[1].modTime_sec = 0x93400031;
     states[1].modTime_nsec = 0xdeadbeef;
+    states[1].mode = 0666; // decimal 438, hex 0x000001b6
     states[1].size = 0x88557766;
     states[1].crc32 = 0x22334422;
     states[1].nameLen = -1;
@@ -641,6 +718,7 @@
 
     states[2].modTime_sec = 0x33221144;
     states[2].modTime_nsec = 0xdeadbeef;
+    states[2].mode = 0744; // decimal 484, hex 0x000001e4
     states[2].size = 0x11223344;
     states[2].crc32 = 0x01122334;
     states[2].nameLen = 0;
@@ -650,6 +728,7 @@
 
     states[3].modTime_sec = 0x33221144;
     states[3].modTime_nsec = 0xdeadbeef;
+    states[3].mode = 0755; // decimal 493, hex 0x000001ed
     states[3].size = 0x11223344;
     states[3].crc32 = 0x01122334;
     states[3].nameLen = 0;
@@ -669,35 +748,38 @@
     static const unsigned char correct_data[] = {
         // header
         0x53, 0x6e, 0x61, 0x70,  0x04, 0x00, 0x00, 0x00,
-        0x46, 0x69, 0x6c, 0x65,  0xac, 0x00, 0x00, 0x00,
+        0x46, 0x69, 0x6c, 0x65,  0xbc, 0x00, 0x00, 0x00,
 
         // bytes_of_padding
         0x98, 0xba, 0xdc, 0xfe,  0xef, 0xbe, 0xad, 0xde,
-        0xbc, 0xbc, 0xab, 0xab,  0x78, 0x56, 0x34, 0x12,
-        0x10, 0x00, 0x00, 0x00,  0x62, 0x79, 0x74, 0x65,
-        0x73, 0x5f, 0x6f, 0x66,  0x5f, 0x70, 0x61, 0x64,
-        0x64, 0x69, 0x6e, 0x67,
+        0xff, 0x01, 0x00, 0x00,  0xbc, 0xbc, 0xab, 0xab,
+        0x78, 0x56, 0x34, 0x12,  0x10, 0x00, 0x00, 0x00,
+        0x62, 0x79, 0x74, 0x65,  0x73, 0x5f, 0x6f, 0x66,
+        0x5f, 0x70, 0x61, 0x64,  0x64, 0x69, 0x6e, 0x67,
 
         // bytes_of_padding3
         0x31, 0x00, 0x40, 0x93,  0xef, 0xbe, 0xad, 0xde,
-        0x66, 0x77, 0x55, 0x88,  0x22, 0x44, 0x33, 0x22,
-        0x11, 0x00, 0x00, 0x00,  0x62, 0x79, 0x74, 0x65,
-        0x73, 0x5f, 0x6f, 0x66,  0x5f, 0x70, 0x61, 0x64,
-        0x64, 0x69, 0x6e, 0x67,  0x33, 0xab, 0xab, 0xab,
+        0xb6, 0x01, 0x00, 0x00,  0x66, 0x77, 0x55, 0x88,
+        0x22, 0x44, 0x33, 0x22,  0x11, 0x00, 0x00, 0x00,
+        0x62, 0x79, 0x74, 0x65,  0x73, 0x5f, 0x6f, 0x66,
+        0x5f, 0x70, 0x61, 0x64,  0x64, 0x69, 0x6e, 0x67,
+        0x33, 0xab, 0xab, 0xab,
 
         // bytes of padding2
         0x44, 0x11, 0x22, 0x33,  0xef, 0xbe, 0xad, 0xde,
-        0x44, 0x33, 0x22, 0x11,  0x34, 0x23, 0x12, 0x01,
-        0x12, 0x00, 0x00, 0x00,  0x62, 0x79, 0x74, 0x65,
-        0x73, 0x5f, 0x6f, 0x66,  0x5f, 0x70, 0x61, 0x64,
-        0x64, 0x69, 0x6e, 0x67,  0x5f, 0x32, 0xab, 0xab,
+        0xe4, 0x01, 0x00, 0x00,  0x44, 0x33, 0x22, 0x11,
+        0x34, 0x23, 0x12, 0x01,  0x12, 0x00, 0x00, 0x00,
+        0x62, 0x79, 0x74, 0x65,  0x73, 0x5f, 0x6f, 0x66,
+        0x5f, 0x70, 0x61, 0x64,  0x64, 0x69, 0x6e, 0x67,
+        0x5f, 0x32, 0xab, 0xab,
 
         // bytes of padding3
         0x44, 0x11, 0x22, 0x33,  0xef, 0xbe, 0xad, 0xde,
-        0x44, 0x33, 0x22, 0x11,  0x34, 0x23, 0x12, 0x01,
-        0x13, 0x00, 0x00, 0x00,  0x62, 0x79, 0x74, 0x65,
-        0x73, 0x5f, 0x6f, 0x66,  0x5f, 0x70, 0x61, 0x64,
-        0x64, 0x69, 0x6e, 0x67,  0x5f, 0x5f, 0x31, 0xab
+        0xed, 0x01, 0x00, 0x00,  0x44, 0x33, 0x22, 0x11,
+        0x34, 0x23, 0x12, 0x01,  0x13, 0x00, 0x00, 0x00,
+        0x62, 0x79, 0x74, 0x65,  0x73, 0x5f, 0x6f, 0x66,
+        0x5f, 0x70, 0x61, 0x64,  0x64, 0x69, 0x6e, 0x67,
+        0x5f, 0x5f, 0x31, 0xab
     };
 
     err = compare_file(filename, correct_data, sizeof(correct_data));
@@ -731,14 +813,14 @@
         const FileState state = readSnapshot.valueAt(i);
 
         if (name != filenames[i] || states[i].modTime_sec != state.modTime_sec
-                || states[i].modTime_nsec != state.modTime_nsec
+                || states[i].modTime_nsec != state.modTime_nsec || states[i].mode != state.mode
                 || states[i].size != state.size || states[i].crc32 != states[i].crc32) {
-            fprintf(stderr, "state %d expected={%d/%d, 0x%08x, 0x%08x, %3d} '%s'\n"
-                            "          actual={%d/%d, 0x%08x, 0x%08x, %3d} '%s'\n", i,
-                    states[i].modTime_sec, states[i].modTime_nsec, states[i].size, states[i].crc32,
-                    name.length(), filenames[i].string(),
-                    state.modTime_sec, state.modTime_nsec, state.size, state.crc32, state.nameLen,
-                    name.string());
+            fprintf(stderr, "state %d expected={%d/%d, 0x%08x, %04o, 0x%08x, %3d} '%s'\n"
+                            "          actual={%d/%d, 0x%08x, %04o, 0x%08x, %3d} '%s'\n", i,
+                    states[i].modTime_sec, states[i].modTime_nsec, states[i].mode, states[i].size,
+                    states[i].crc32, name.length(), filenames[i].string(),
+                    state.modTime_sec, state.modTime_nsec, state.mode, state.size, state.crc32,
+                    state.nameLen, name.string());
             matched = false;
         }
     }
@@ -839,6 +921,7 @@
     size_t actualSize;
     bool done;
     int type;
+    ssize_t nRead;
 
     // printf("\n\n---------- test_read_header_and_entity -- %s\n\n", str);
 
@@ -873,8 +956,9 @@
         goto finished;
     }
 
-    err = reader.ReadEntityData(buf, bufSize);
-    if (err != NO_ERROR) {
+    nRead = reader.ReadEntityData(buf, bufSize);
+    if (nRead < 0) {
+        err = reader.Status();
         fprintf(stderr, "ReadEntityData failed with %s\n", strerror(err));
         goto finished;
     }
diff --git a/libs/utils/ResourceTypes.cpp b/libs/utils/ResourceTypes.cpp
index 69d47f0..e4f9f0f 100644
--- a/libs/utils/ResourceTypes.cpp
+++ b/libs/utils/ResourceTypes.cpp
@@ -544,7 +544,7 @@
     return mEventCode;
 }
 
-const int32_t ResXMLParser::getCommentID() const
+int32_t ResXMLParser::getCommentID() const
 {
     return mCurNode != NULL ? dtohl(mCurNode->comment.index) : -1;
 }
@@ -555,12 +555,12 @@
     return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
 }
 
-const uint32_t ResXMLParser::getLineNumber() const
+uint32_t ResXMLParser::getLineNumber() const
 {
     return mCurNode != NULL ? dtohl(mCurNode->lineNumber) : -1;
 }
 
-const int32_t ResXMLParser::getTextID() const
+int32_t ResXMLParser::getTextID() const
 {
     if (mEventCode == TEXT) {
         return dtohl(((const ResXMLTree_cdataExt*)mCurExt)->data.index);
@@ -583,7 +583,7 @@
     return BAD_TYPE;
 }
 
-const int32_t ResXMLParser::getNamespacePrefixID() const
+int32_t ResXMLParser::getNamespacePrefixID() const
 {
     if (mEventCode == START_NAMESPACE || mEventCode == END_NAMESPACE) {
         return dtohl(((const ResXMLTree_namespaceExt*)mCurExt)->prefix.index);
@@ -598,7 +598,7 @@
     return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
 }
 
-const int32_t ResXMLParser::getNamespaceUriID() const
+int32_t ResXMLParser::getNamespaceUriID() const
 {
     if (mEventCode == START_NAMESPACE || mEventCode == END_NAMESPACE) {
         return dtohl(((const ResXMLTree_namespaceExt*)mCurExt)->uri.index);
@@ -613,7 +613,7 @@
     return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
 }
 
-const int32_t ResXMLParser::getElementNamespaceID() const
+int32_t ResXMLParser::getElementNamespaceID() const
 {
     if (mEventCode == START_TAG) {
         return dtohl(((const ResXMLTree_attrExt*)mCurExt)->ns.index);
@@ -630,7 +630,7 @@
     return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
 }
 
-const int32_t ResXMLParser::getElementNameID() const
+int32_t ResXMLParser::getElementNameID() const
 {
     if (mEventCode == START_TAG) {
         return dtohl(((const ResXMLTree_attrExt*)mCurExt)->name.index);
@@ -655,7 +655,7 @@
     return 0;
 }
 
-const int32_t ResXMLParser::getAttributeNamespaceID(size_t idx) const
+int32_t ResXMLParser::getAttributeNamespaceID(size_t idx) const
 {
     if (mEventCode == START_TAG) {
         const ResXMLTree_attrExt* tag = (const ResXMLTree_attrExt*)mCurExt;
@@ -678,7 +678,7 @@
     return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
 }
 
-const int32_t ResXMLParser::getAttributeNameID(size_t idx) const
+int32_t ResXMLParser::getAttributeNameID(size_t idx) const
 {
     if (mEventCode == START_TAG) {
         const ResXMLTree_attrExt* tag = (const ResXMLTree_attrExt*)mCurExt;
@@ -701,7 +701,7 @@
     return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL;
 }
 
-const uint32_t ResXMLParser::getAttributeNameResID(size_t idx) const
+uint32_t ResXMLParser::getAttributeNameResID(size_t idx) const
 {
     int32_t id = getAttributeNameID(idx);
     if (id >= 0 && (size_t)id < mTree.mNumResIds) {
@@ -710,7 +710,7 @@
     return 0;
 }
 
-const int32_t ResXMLParser::getAttributeValueStringID(size_t idx) const
+int32_t ResXMLParser::getAttributeValueStringID(size_t idx) const
 {
     if (mEventCode == START_TAG) {
         const ResXMLTree_attrExt* tag = (const ResXMLTree_attrExt*)mCurExt;
diff --git a/location/java/com/android/internal/location/GpsLocationProvider.java b/location/java/com/android/internal/location/GpsLocationProvider.java
index e4ff0e3..edd1ea0 100755
--- a/location/java/com/android/internal/location/GpsLocationProvider.java
+++ b/location/java/com/android/internal/location/GpsLocationProvider.java
@@ -621,23 +621,37 @@
     }
 
     public void addListener(int uid) {
-        mClientUids.put(uid, 0);
-        if (mNavigating) {
-            try {
-                mBatteryStats.noteStartGps(uid);
-            } catch (RemoteException e) {
-                Log.w(TAG, "RemoteException in addListener");
+        synchronized(mListeners) {
+            if (mClientUids.indexOfKey(uid) >= 0) {
+                // Shouldn't be here -- already have this uid.
+                Log.w(TAG, "Duplicate add listener for uid " + uid);
+                return;
+            }
+            mClientUids.put(uid, 0);
+            if (mNavigating) {
+                try {
+                    mBatteryStats.noteStartGps(uid);
+                } catch (RemoteException e) {
+                    Log.w(TAG, "RemoteException in addListener");
+                }
             }
         }
     }
 
     public void removeListener(int uid) {
-        mClientUids.delete(uid);
-        if (mNavigating) {
-            try {
-                mBatteryStats.noteStopGps(uid);
-            } catch (RemoteException e) {
-                Log.w(TAG, "RemoteException in removeListener");
+        synchronized(mListeners) {
+            if (mClientUids.indexOfKey(uid) < 0) {
+                // Shouldn't be here -- don't have this uid.
+                Log.w(TAG, "Unneeded remove listener for uid " + uid);
+                return;
+            }
+            mClientUids.delete(uid);
+            if (mNavigating) {
+                try {
+                    mBatteryStats.noteStopGps(uid);
+                } catch (RemoteException e) {
+                    Log.w(TAG, "RemoteException in removeListener");
+                }
             }
         }
     }
@@ -836,30 +850,33 @@
     private void reportStatus(int status) {
         if (VERBOSE) Log.v(TAG, "reportStatus status: " + status);
 
-        boolean wasNavigating = mNavigating;
-        mNavigating = (status == GPS_STATUS_SESSION_BEGIN);
-
-        if (wasNavigating != mNavigating) {
+        synchronized(mListeners) {
+            boolean wasNavigating = mNavigating;
+            mNavigating = (status == GPS_STATUS_SESSION_BEGIN);
+    
+            if (wasNavigating == mNavigating) {
+                return;
+            }
+            
             if (mNavigating) {
                 if (DEBUG) Log.d(TAG, "Acquiring wakelock");
                  mWakeLock.acquire();
             }
-            synchronized(mListeners) {
-                int size = mListeners.size();
-                for (int i = 0; i < size; i++) {
-                    Listener listener = mListeners.get(i);
-                    try {
-                        if (mNavigating) {
-                            listener.mListener.onGpsStarted(); 
-                        } else {
-                            listener.mListener.onGpsStopped(); 
-                        }
-                    } catch (RemoteException e) {
-                        Log.w(TAG, "RemoteException in reportStatus");
-                        mListeners.remove(listener);
-                        // adjust for size of list changing
-                        size--;
+        
+            int size = mListeners.size();
+            for (int i = 0; i < size; i++) {
+                Listener listener = mListeners.get(i);
+                try {
+                    if (mNavigating) {
+                        listener.mListener.onGpsStarted(); 
+                    } else {
+                        listener.mListener.onGpsStopped(); 
                     }
+                } catch (RemoteException e) {
+                    Log.w(TAG, "RemoteException in reportStatus");
+                    mListeners.remove(listener);
+                    // adjust for size of list changing
+                    size--;
                 }
             }
 
@@ -949,8 +966,13 @@
                  int result = mConnMgr.startUsingNetworkFeature(
                         ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_SUPL);
                 if (result == Phone.APN_ALREADY_ACTIVE) {
-                    native_agps_data_conn_open(mAGpsApn);
-                    mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
+                    if (mAGpsApn != null) {
+                        native_agps_data_conn_open(mAGpsApn);
+                        mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPEN;
+                    } else {
+                        Log.e(TAG, "mAGpsApn not set when receiving Phone.APN_ALREADY_ACTIVE");
+                        native_agps_data_conn_failed();
+                    }
                 } else if (result == Phone.APN_REQUEST_STARTED) {
                     mAGpsDataConnectionState = AGPS_DATA_CONNECTION_OPENING;
                 } else {
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 3b46d69..298cce9 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -23,6 +23,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
 import android.os.PowerManager;
 import android.util.Log;
@@ -435,6 +436,10 @@
     }
 
     private final static String TAG = "MediaPlayer";
+    // Name of the remote interface for the media player. Must be kept
+    // in sync with the 2nd parameter of the IMPLEMENT_META_INTERFACE
+    // macro invocation in IMediaPlayer.cpp
+    private final static String IMEDIA_PLAYER = "android.media.IMediaPlayer";
 
     private int mNativeContext; // accessed by native methods
     private int mListenerContext; // accessed by native methods
@@ -475,6 +480,43 @@
     private native void _setVideoSurface();
 
     /**
+     * Create a request parcel which can be routed to the native media
+     * player using {@link #invoke(Parcel, Parcel)}. The Parcel
+     * returned has the proper InterfaceToken set. The caller should
+     * not overwrite that token, i.e it can only append data to the
+     * Parcel.
+     *
+     * @return A parcel suitable to hold a request for the native
+     * player.
+     */
+    public Parcel newRequest() {
+        Parcel parcel = Parcel.obtain();
+        parcel.writeInterfaceToken(IMEDIA_PLAYER);
+        return parcel;
+    }
+
+    /**
+     * Invoke a generic method on the native player using opaque
+     * parcels for the request and reply. Both payloads' format is a
+     * convention between the java caller and the native player.
+     * Must be called after setDataSource to make sure a native player
+     * exists.
+     *
+     * @param request Parcel with the data for the extension. The
+     * caller must use {@link #newRequest()} to get one.
+     *
+     * @param[out] reply Parcel with the data returned by the
+     * native player.
+     *
+     * @return The status code see utils/Errors.h
+     */
+    public int invoke(Parcel request, Parcel reply) {
+        int retcode = native_invoke(request, reply);
+        reply.setDataPosition(0);
+        return retcode;
+    }
+
+    /**
      * Sets the SurfaceHolder to use for displaying the video portion of the media.
      * This call is optional. Not calling it when playing back a video will
      * result in only the audio track being played.
@@ -915,8 +957,18 @@
      */
     public native Bitmap getFrameAt(int msec) throws IllegalStateException;
 
+    /**
+     * @param request Parcel destinated to the media player. The
+     *                Interface token must be set to the IMediaPlayer
+     *                one to be routed correctly through the system.
+     * @param reply Parcel that will contain the reply.
+     * @return The status code.
+     */
+    private native final int native_invoke(Parcel request, Parcel reply);
+
     private native final void native_setup(Object mediaplayer_this);
     private native final void native_finalize();
+
     @Override
     protected void finalize() { native_finalize(); }
 
diff --git a/media/java/android/media/ToneGenerator.java b/media/java/android/media/ToneGenerator.java
index 54ca6c4..e5ee9a3 100644
--- a/media/java/android/media/ToneGenerator.java
+++ b/media/java/android/media/ToneGenerator.java
@@ -50,12 +50,12 @@
      *
      * @see #ToneGenerator(int, int)
      */
-   public static final int TONE_DTMF_2 = 2;
-   /**
-    * DTMF tone for key 3: 1477Hz, 697Hz, continuous
-    *
-    * @see #ToneGenerator(int, int)
-    */
+    public static final int TONE_DTMF_2 = 2;
+    /**
+     * DTMF tone for key 3: 1477Hz, 697Hz, continuous
+     *
+     * @see #ToneGenerator(int, int)
+     */
     public static final int TONE_DTMF_3 = 3;
     /**
      * DTMF tone for key 4: 1209Hz, 770Hz, continuous
@@ -254,242 +254,474 @@
      * @see #ToneGenerator(int, int)
      */
     public static final int TONE_SUP_PIP = 33;
-
-
     /**
-     * CDMA SPECIFIC TONES START
-     */
-
-    /** TODO(Moto): Change "Proprietary" below with an appropriate specification reference */
-
-    /**
-     * Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON
+     *  CDMA Dial tone : 425Hz  continuous
      *
      * @see #ToneGenerator(int, int)
-     *
-     * @hide
      */
     public static final int TONE_CDMA_DIAL_TONE_LITE = 34;
-
-     /**
-     * Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON
+    /**
+     * CDMA USA Ringback: 440Hz+480Hz 2s ON, 4000 OFF ...
      *
      * @see #ToneGenerator(int, int)
-     *
-     * @hide
      */
     public static final int TONE_CDMA_NETWORK_USA_RINGBACK = 35;
-
     /**
-     * Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON
+     *  CDMA Intercept tone: 440Hz 250ms ON, 620Hz 250ms ON ...
      *
      * @see #ToneGenerator(int, int)
-     *
-     * @hide
      */
-    public static final int TONE_CDMA_REORDER = 36;
-
-   /**
-     * Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON
-     *
-     * @see #ToneGenerator(int, int)
-     *
-     * @hide
-     */
-     public static final int TONE_CDMA_ABBR_REORDER = 37;
-
-   /**
-     * Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON
-     *
-     * @see #ToneGenerator(int, int)
-     *
-     * @hide
-     */
-     public static final int TONE_CDMA_NETWORK_BUSY = 38;
-
-
-   /**
-     * Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON
-     *
-     * @see #ToneGenerator(int, int)
-     *
-     * @hide
-     */
-    public static final int TONE_CDMA_ANSWER = 39;
-
-   /**
-     * Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON
-     *
-     * @see #ToneGenerator(int, int)
-     *
-     * @hide
-     */
-    public static final int TONE_CDMA_NETWORK_CALLWAITING = 40;
-
-   /**
-     * Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON
-     *
-     * @see #ToneGenerator(int, int)
-     *
-     * @hide
-     */
-    public static final int TONE_CDMA_PIP = 41;
-
-
+    public static final int TONE_CDMA_INTERCEPT = 36;
     /**
-     * Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON
+     * CDMA Abbr Intercept tone: 440Hz 250ms ON, 620Hz 250ms ON
      *
      * @see #ToneGenerator(int, int)
-     *
-     * @hide
      */
-    public static final int TONE_CDMA_CALL_SIGNAL_ISDN_NORMAL = 42;
-
+    public static final int TONE_CDMA_ABBR_INTERCEPT = 37;
     /**
-     * Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON
+     * CDMA Reorder tone: 480Hz+620Hz 250ms ON, 250ms OFF...
      *
      * @see #ToneGenerator(int, int)
-     *
-     * @hide
      */
-    public static final int TONE_CDMA_CALL_SIGNAL_ISDN_INTERGROUP = 43;
-
-     /**
-     * Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON
-     *
-     * @see #ToneGenerator(int, int)
-     *
-     * @hide
-     */
-    public static final int TONE_CDMA_CALL_SIGNAL_SP_PRI = 44;
-
+    public static final int TONE_CDMA_REORDER = 38;
     /**
-     * Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON
      *
+     * CDMA Abbr Reorder tone: 480Hz+620Hz 250ms ON, 250ms OFF repeated for 8 times
      * @see #ToneGenerator(int, int)
-     *
-     * @hide
      */
-    public static final int TONE_CDMA_CALL_SIGNAL_ISDN_PAT3 = 45;
-
+    public static final int TONE_CDMA_ABBR_REORDER = 39;
     /**
-     * Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON
+     * CDMA Network Busy tone: 480Hz+620Hz 500ms ON, 500ms OFF continuous
      *
      * @see #ToneGenerator(int, int)
-     *
-     * @hide
      */
-    public static final int TONE_CDMA_CALL_SIGNAL_ISDN_RING_RING = 46;
-
+    public static final int TONE_CDMA_NETWORK_BUSY = 40;
     /**
-     * Proprietary tone, general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON
+     * CDMA Confirm tone: 350Hz+440Hz 100ms ON, 100ms OFF repeated for 3 times
      *
      * @see #ToneGenerator(int, int)
-     *
-     * @hide
      */
-    public static final int TONE_CDMA_CALL_SIGNAL_ISDN_PAT5 = 47;
-
+    public static final int TONE_CDMA_CONFIRM = 41;
     /**
-     * general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON
      *
+     * CDMA answer tone: silent tone - defintion Frequency 0, 0ms ON, 0ms OFF
      * @see #ToneGenerator(int, int)
-     *
-     * @hide
      */
-    public static final int TONE_CDMA_CALL_SIGNAL_ISDN_PAT6 = 48;
-
+    public static final int TONE_CDMA_ANSWER = 42;
     /**
-     * general double beep: twice 400Hz+1200Hz, 35ms ON, 200ms OFF, 35ms ON
+     *
+     * CDMA Network Callwaiting tone: 440Hz 300ms ON
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_NETWORK_CALLWAITING = 43;
+    /**
+     * CDMA PIP tone: 480Hz 100ms ON, 100ms OFF repeated for 4 times
      *
      * @see #ToneGenerator(int, int)
-     *
-     * @hide
      */
-    public static final int TONE_CDMA_CALL_SIGNAL_ISDN_PAT7 = 49;
-
-    // TODO(Moto): Need comments for each one and we need ToneGenerator.cpp/ToneGenerator.h
-
-    /** @hide */
-    public static final int TONE_CDMA_HIGH_L = 50;
-
-    /** @hide */
-    public static final int TONE_CDMA_LOW_L = 51;
-    /** @hide */
-    public static final int TONE_CDMA_HIGH_SS = 52;
-    /** @hide */
-    public static final int TONE_CDMA_MED_SS = 53;
-    /** @hide */
-    public static final int TONE_CDMA_LOW_SS = 54;
-    /** @hide */
-    public static final int TONE_CDMA_HIGH_SSL = 55;
-
-
-    /** @hide */
-    public static final int TONE_CDMA_MED_SSL = 56;
-    /** @hide */
-    public static final int TONE_CDMA_LOW_SSL = 57;
-    /** @hide */
-    public static final int TONE_CDMA_HIGH_SS_2 = 58;
-    /** @hide */
-    public static final int TONE_CDMA_MED_SS_2 = 59;
-    /** @hide */
-    public static final int TONE_CDMA_LOW_SS_2 = 60;
-    /** @hide */
-    public static final int TONE_CDMA_HIGH_SLS = 61;
-    /** @hide */
-    public static final int TONE_CDMA_MED_SLS = 62;
-    /** @hide */
-    public static final int TONE_CDMA_LOW_SLS = 63;
-    /** @hide */
-    public static final int TONE_CDMA_HIGH_S_X4 = 64;
-    /** @hide */
-    public static final int TONE_CDMA_MED_S_X4 = 65;
-    /** @hide */
-    public static final int TONE_CDMA_LOW_S_X4 = 66;
-    /** @hide */
-    public static final int TONE_CDMA_HIGH_PBX_L = 67;
-    /** @hide */
-    public static final int TONE_CDMA_MED_PBX_L = 68;
-    /** @hide */
-    public static final int TONE_CDMA_LOW_PBX_L = 69;
-    /** @hide */
-    public static final int TONE_CDMA_HIGH_PBX_SS = 70;
-    /** @hide */
-    public static final int TONE_CDMA_MED_PBX_SS = 71;
-    /** @hide */
-    public static final int TONE_CDMA_LOW_PBX_SS = 72;
-    /** @hide */
-    public static final int TONE_CDMA_HIGH_PBX_SSL = 73;
-    /** @hide */
-    public static final int TONE_CDMA_MED_PBX_SSL = 74;
-
-    /** @hide */
-    public static final int TONE_CDMA_LOW_PBX_SSL = 75;
-    /** @hide */
-    public static final int TONE_CDMA_HIGH_PBX_SLS = 76;
-    /** @hide */
-    public static final int TONE_CDMA_MED_PBX_SLS = 77;
-    /** @hide */
-    public static final int TONE_CDMA_LOW_PBX_SLS = 78;
-    /** @hide */
-    public static final int TONE_CDMA_HIGH_PBX_S_X4 = 79;
-    /** @hide */
-    public static final int TONE_CDMA_MED_PBX_S_X4 = 80;
-    /** @hide */
-    public static final int TONE_CDMA_LOW_PBX_S_X4 = 81;
-    /** @hide */
-    public static final int TONE_CDMA_INTERCEPT_ONE_SHOT = TONE_SUP_INTERCEPT_ABBREV;
-    /** @hide */
-    public static final int TONE_CDMA_REORDER_ONE_SHOT = TONE_CDMA_ABBR_REORDER;
-    /** @hide */
-    public static final int TONE_CDMA_NETWORK_BUSY_ONE_SHOT = 82;
-    /** @hide */
-    public static final int TONE_CDMA_ABBR_ALERT = 83;
-    /** @hide */
-    public static final int TONE_CDMA_SIGNAL_OFF = 84;
-    /** @hide */
-    public static final int TONE_CDMA_INVALID = 85;
+    public static final int TONE_CDMA_PIP = 44;
+    /**
+     *  ISDN Call Signal Normal tone: {2091Hz 32ms ON, 2556 64ms ON} 20 times,
+     *  2091 32ms ON, 2556 48ms ON, 4s OFF
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_CALL_SIGNAL_ISDN_NORMAL = 45;
+    /**
+     *  ISDN Call Signal Intergroup tone: {2091Hz 32ms ON, 2556 64ms ON} 8 times,
+     * 2091Hz 32ms ON, 400ms OFF, {2091Hz 32ms ON, 2556Hz 64ms ON} times,
+     * 2091Hz 32ms ON, 4s OFF.
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_CALL_SIGNAL_ISDN_INTERGROUP = 46;
+    /**
+     * ISDN Call Signal SP PRI tone:{2091Hz 32ms ON, 2556 64ms ON} 4 times
+     * 2091Hz 16ms ON, 200ms OFF, {2091Hz 32ms ON, 2556Hz 64ms ON} 4 times,
+     * 2091Hz 16ms ON, 200ms OFF
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_CALL_SIGNAL_ISDN_SP_PRI = 47;
+    /**
+     * ISDN Call sign PAT3 tone: silent tone
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_CALL_SIGNAL_ISDN_PAT3 = 48;
+    /**
+     * ISDN Ping Ring tone: {2091Hz 32ms ON, 2556Hz 64ms ON} 5 times
+     * 2091Hz 20ms ON
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_CALL_SIGNAL_ISDN_PING_RING = 49;
+    /**
+     *
+     * ISDN Pat5 tone: silent tone
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_CALL_SIGNAL_ISDN_PAT5 = 50;
+    /**
+     *
+     * ISDN Pat6 tone: silent tone
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_CALL_SIGNAL_ISDN_PAT6 = 51;
+    /**
+     * ISDN Pat7 tone: silent tone
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_CALL_SIGNAL_ISDN_PAT7 = 52;
+    /**
+     * TONE_CDMA_HIGH_L tone: {3700Hz 25ms, 4000Hz 25ms} 40 times
+     * 4000ms OFF, Repeat ....
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_HIGH_L = 53;
+    /**
+     * TONE_CDMA_MED_L tone: {2600Hz 25ms, 2900Hz 25ms} 40 times
+     * 4000ms OFF, Repeat ....
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_MED_L = 54;
+    /**
+     * TONE_CDMA_LOW_L tone: {1300Hz 25ms, 1450Hz 25ms} 40 times,
+     * 4000ms OFF, Repeat ....
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_LOW_L = 55;
+    /**
+     * CDMA HIGH SS tone: {3700Hz 25ms, 4000Hz 25ms} repeat 16 times,
+     * 400ms OFF, repeat ....
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_HIGH_SS = 56;
+    /**
+     * CDMA MED SS tone: {2600Hz 25ms, 2900Hz 25ms} repeat 16 times,
+     * 400ms OFF, repeat ....
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_MED_SS = 57;
+    /**
+     * CDMA LOW SS tone: {1300z 25ms, 1450Hz 25ms} repeat 16 times,
+     * 400ms OFF, repeat ....
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_LOW_SS = 58;
+    /**
+     * CDMA HIGH SSL tone: {3700Hz 25ms, 4000Hz 25ms} 8 times,
+     * 200ms OFF, {3700Hz 25ms, 4000Hz 25ms} repeat 8 times,
+     * 200ms OFF, {3700Hz 25ms, 4000Hz 25ms} repeat 16 times,
+     * 4000ms OFF, repeat ...
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_HIGH_SSL = 59;
+    /**
+     * CDMA MED SSL tone: {2600Hz 25ms, 2900Hz 25ms} 8 times,
+     * 200ms OFF, {2600Hz 25ms, 2900Hz 25ms} repeat 8 times,
+     * 200ms OFF, {2600Hz 25ms, 2900Hz 25ms} repeat 16 times,
+     * 4000ms OFF, repeat ...
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_MED_SSL = 60;
+    /**
+     * CDMA LOW SSL tone: {1300Hz 25ms, 1450Hz 25ms} 8 times,
+     * 200ms OFF, {1300Hz 25ms, 1450Hz 25ms} repeat 8 times,
+     * 200ms OFF, {1300Hz 25ms, 1450Hz 25ms} repeat 16 times,
+     * 4000ms OFF, repeat ...
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_LOW_SSL = 61;
+    /**
+     * CDMA HIGH SS2 tone: {3700Hz 25ms, 4000Hz 25ms} 20 times,
+     * 1000ms OFF, {3700Hz 25ms, 4000Hz 25ms} 20 times,
+     * 3000ms OFF, repeat ....
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_HIGH_SS_2 = 62;
+    /**
+     * CDMA MED SS2 tone: {2600Hz 25ms, 2900Hz 25ms} 20 times,
+     * 1000ms OFF, {2600Hz 25ms, 2900Hz 25ms} 20 times,
+     * 3000ms OFF, repeat ....
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_MED_SS_2 = 63;
+    /**
+     * CDMA LOW SS2 tone: {1300Hz 25ms, 1450Hz 25ms} 20 times,
+     * 1000ms OFF, {1300Hz 25ms, 1450Hz 25ms} 20 times,
+     * 3000ms OFF, repeat ....
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_LOW_SS_2 = 64;
+    /**
+     *  CDMA HIGH SLS tone: {3700Hz 25ms, 4000Hz 25ms} 10 times,
+     *  500ms OFF, {3700Hz 25ms, 4000Hz 25ms} 20 times, 500ms OFF,
+     *  {3700Hz 25ms, 4000Hz 25ms} 10 times, 3000ms OFF, REPEAT
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_HIGH_SLS = 65;
+    /**
+     *  CDMA MED  SLS tone: {2600Hz 25ms, 2900Hz 25ms} 10 times,
+     *  500ms OFF, {2600Hz 25ms, 2900Hz 25ms} 20 times, 500ms OFF,
+     *  {2600Hz 25ms, 2900Hz 25ms} 10 times, 3000ms OFF, REPEAT
+     *
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_MED_SLS = 66;
+    /**
+     *  CDMA LOW SLS tone: {1300Hz 25ms, 1450Hz 25ms} 10 times,
+     *  500ms OFF, {1300Hz 25ms, 1450Hz 25ms} 20 times, 500ms OFF,
+     *  {1300Hz 25ms, 1450Hz 25ms} 10 times, 3000ms OFF, REPEAT
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_LOW_SLS = 67;
+    /**
+     *  CDMA HIGH S X4 tone: {3700Hz 25ms, 4000Hz 25ms} 10 times,
+     *  500ms OFF, {3700Hz 25ms, 4000Hz 25ms} 10 times, 500ms OFF,
+     *  {3700Hz 25ms, 4000Hz 25ms} 10 times, 500ms OFF,
+     *  {3700Hz 25ms, 4000Hz 25ms} 10 times, 2500ms OFF, REPEAT....
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_HIGH_S_X4 = 68;
+    /**
+     *  CDMA MED S X4 tone: {2600Hz 25ms, 2900Hz 25ms} 10 times,
+     *  500ms OFF, {2600Hz 25ms, 2900Hz 25ms} 10 times, 500ms OFF,
+     *  {2600Hz 25ms, 2900Hz 25ms} 10 times, 500ms OFF,
+     *  {2600Hz 25ms, 2900Hz 25ms} 10 times, 2500ms OFF, REPEAT....
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_MED_S_X4 = 69;
+    /**
+     *  CDMA LOW  S X4 tone: {2600Hz 25ms, 2900Hz 25ms} 10 times,
+     *  500ms OFF, {2600Hz 25ms, 2900Hz 25ms} 10 times, 500ms OFF,
+     *  {2600Hz 25ms, 2900Hz 25ms} 10 times, 500ms OFF,
+     *  {2600Hz 25ms, 2900Hz 25ms} 10 times, 2500ms OFF, REPEAT....
+     *
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_LOW_S_X4 = 70;
+    /**
+     * CDMA HIGH PBX L: {3700Hz 25ms, 4000Hz 25ms}20 times,
+     * 2000ms OFF,  REPEAT....
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_HIGH_PBX_L = 71;
+    /**
+     *  CDMA MED PBX L: {2600Hz 25ms, 2900Hz 25ms}20 times,
+     * 2000ms OFF,  REPEAT....
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_MED_PBX_L = 72;
+    /**
+     * CDMA LOW PBX L: {1300Hz 25ms,1450Hz 25ms}20 times,
+     * 2000ms OFF,  REPEAT....
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_LOW_PBX_L = 73;
+    /**
+     * CDMA HIGH PBX SS tone: {3700Hz 25ms, 4000Hz 25ms} 8 times
+     * 200 ms OFF, {3700Hz 25ms 4000Hz 25ms}8 times,
+     * 2000ms OFF, REPEAT....
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_HIGH_PBX_SS = 74;
+    /**
+     * CDMA MED PBX SS tone: {2600Hz 25ms, 2900Hz 25ms} 8 times
+     * 200 ms OFF, {2600Hz 25ms 2900Hz 25ms}8 times,
+     * 2000ms OFF, REPEAT....
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_MED_PBX_SS = 75;
+    /**
+     * CDMA LOW PBX SS tone: {1300Hz 25ms, 1450Hz 25ms} 8 times
+     * 200 ms OFF, {1300Hz 25ms 1450Hz 25ms}8 times,
+     * 2000ms OFF, REPEAT....
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_LOW_PBX_SS = 76;
+    /**
+     * CDMA HIGH PBX SSL tone:{3700Hz 25ms, 4000Hz 25ms} 8 times
+     * 200ms OFF, {3700Hz 25ms, 4000Hz 25ms} 8 times, 200ms OFF,
+     * {3700Hz 25ms, 4000Hz 25ms} 16 times, 1000ms OFF, REPEAT....
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_HIGH_PBX_SSL = 77;
+    /**
+     * CDMA MED PBX SSL tone:{2600Hz 25ms, 2900Hz 25ms} 8 times
+     * 200ms OFF, {2600Hz 25ms, 2900Hz 25ms} 8 times, 200ms OFF,
+     * {2600Hz 25ms, 2900Hz 25ms} 16 times, 1000ms OFF, REPEAT....
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_MED_PBX_SSL = 78;
+    /**
+     * CDMA LOW PBX SSL tone:{1300Hz 25ms, 1450Hz 25ms} 8 times
+     * 200ms OFF, {1300Hz 25ms, 1450Hz 25ms} 8 times, 200ms OFF,
+     * {1300Hz 25ms, 1450Hz 25ms} 16 times, 1000ms OFF, REPEAT....
+     *
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_LOW_PBX_SSL = 79;
+    /**
+     * CDMA HIGH PBX SSL tone:{3700Hz 25ms, 4000Hz 25ms} 8 times
+     * 200ms OFF, {3700Hz 25ms, 4000Hz 25ms} 16 times, 200ms OFF,
+     * {3700Hz 25ms, 4000Hz 25ms} 8 times, 1000ms OFF, REPEAT....
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_HIGH_PBX_SLS = 80;
+    /**
+     * CDMA HIGH PBX SLS tone:{2600Hz 25ms, 2900Hz 25ms} 8 times
+     * 200ms OFF, {2600Hz 25ms, 2900Hz 25ms} 16 times, 200ms OFF,
+     * {2600Hz 25ms, 2900Hz 25ms} 8 times, 1000ms OFF, REPEAT....
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_MED_PBX_SLS = 81;
+    /**
+     * CDMA HIGH PBX SLS tone:{1300Hz 25ms, 1450Hz 25ms} 8 times
+     * 200ms OFF, {1300Hz 25ms, 1450Hz 25ms} 16 times, 200ms OFF,
+     * {1300Hz 25ms, 1450Hz 25ms} 8 times, 1000ms OFF, REPEAT....
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_LOW_PBX_SLS = 82;
+    /**
+     * CDMA HIGH PBX X S4 tone: {3700Hz 25ms 4000Hz 25ms} 8 times,
+     * 200ms OFF, {3700Hz 25ms 4000Hz 25ms} 8 times, 200ms OFF,
+     * {3700Hz 25ms 4000Hz 25ms} 8 times, 200ms OFF,
+     * {3700Hz 25ms 4000Hz 25ms} 8 times, 800ms OFF, REPEAT...
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_HIGH_PBX_S_X4 = 83;
+    /**
+     * CDMA MED PBX X S4 tone: {2600Hz 25ms 2900Hz 25ms} 8 times,
+     * 200ms OFF, {2600Hz 25ms 2900Hz 25ms} 8 times, 200ms OFF,
+     * {2600Hz 25ms 2900Hz 25ms} 8 times, 200ms OFF,
+     * {2600Hz 25ms 2900Hz 25ms} 8 times, 800ms OFF, REPEAT...
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_MED_PBX_S_X4 = 84;
+    /**
+     * CDMA LOW PBX X S4 tone: {1300Hz 25ms 1450Hz 25ms} 8 times,
+     * 200ms OFF, {1300Hz 25ms 1450Hz 25ms} 8 times, 200ms OFF,
+     * {1300Hz 25ms 1450Hz 25ms} 8 times, 200ms OFF,
+     * {1300Hz 25ms 1450Hz 25ms} 8 times, 800ms OFF, REPEAT...
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_LOW_PBX_S_X4 = 85;
+    /**
+     * CDMA Alert Network Lite tone: 1109Hz 62ms ON, 784Hz 62ms ON, 740Hz 62ms ON
+     * 622Hz 62ms ON, 1109Hz 62ms ON
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int    TONE_CDMA_ALERT_NETWORK_LITE = 86;
+    /**
+     * CDMA Alert Auto Redial tone: {1245Hz 62ms ON, 659Hz 62ms ON} 3 times,
+     * 1245 62ms ON
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int    TONE_CDMA_ALERT_AUTOREDIAL_LITE = 87;
+    /**
+     * CDMA One Min Beep tone: 1150Hz+770Hz 400ms ON
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int    TONE_CDMA_ONE_MIN_BEEP = 88;
+    /**
+     *
+     * CDMA KEYPAD Volume key lite tone: 941Hz+1477Hz 120ms ON
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int    TONE_CDMA_KEYPAD_VOLUME_KEY_LITE = 89;
+    /**
+     * CDMA PRESSHOLDKEY LITE tone: 587Hz 375ms ON, 1175Hz 125ms ON
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int    TONE_CDMA_PRESSHOLDKEY_LITE = 90;
+    /**
+     * CDMA ALERT INCALL LITE tone: 587Hz 62ms, 784 62ms, 831Hz 62ms,
+     * 784Hz 62ms, 1109 62ms, 784Hz 62ms, 831Hz 62ms, 784Hz 62ms
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int    TONE_CDMA_ALERT_INCALL_LITE = 91;
+    /**
+     * CDMA EMERGENCY RINGBACK tone: {941Hz 125ms ON, 10ms OFF} 3times
+     * 4990ms OFF, REPEAT...
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int    TONE_CDMA_EMERGENCY_RINGBACK = 92;
+    /**
+     * CDMA ALERT CALL GUARD tone: {1319Hz 125ms ON, 125ms OFF} 3 times
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int    TONE_CDMA_ALERT_CALL_GUARD = 93;
+    /**
+     * CDMA SOFT ERROR LITE  tone: 1047Hz 125ms ON, 370Hz 125ms
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int    TONE_CDMA_SOFT_ERROR_LITE = 94;
+    /**
+     * CDMA CALLDROP LITE tone: 1480Hz 125ms, 1397Hz 125ms, 784Hz 125ms
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int    TONE_CDMA_CALLDROP_LITE = 95;
+    /**
+     * CDMA_NETWORK_BUSY_ONE_SHOT tone: 425Hz 500ms ON, 500ms OFF.
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int    TONE_CDMA_NETWORK_BUSY_ONE_SHOT = 96;
+    /**
+     * CDMA_ABBR_ALERT tone: 1150Hz+770Hz 400ms ON
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int    TONE_CDMA_ABBR_ALERT = 97;
+    /**
+     * CDMA_SIGNAL_OFF - silent tone
+     *
+     * @see #ToneGenerator(int, int)
+     */
+    public static final int TONE_CDMA_SIGNAL_OFF = 98;
 
     /** Maximum volume, for use with {@link #ToneGenerator(int,int)} */
     public static final int MAX_VOLUME = AudioSystem.MAX_VOLUME;
@@ -546,6 +778,71 @@
      * <li>{@link #TONE_SUP_CONGESTION_ABBREV}
      * <li>{@link #TONE_SUP_CONFIRM}
      * <li>{@link #TONE_SUP_PIP}
+     * <li>{@link #TONE_CDMA_DIAL_TONE_LITE}
+     * <li>{@link #TONE_CDMA_NETWORK_USA_RINGBACK}
+     * <li>{@link #TONE_CDMA_INTERCEPT}
+     * <li>{@link #TONE_CDMA_ABBR_INTERCEPT}
+     * <li>{@link #TONE_CDMA_REORDER}
+     * <li>{@link #TONE_CDMA_ABBR_REORDER}
+     * <li>{@link #TONE_CDMA_NETWORK_BUSY}
+     * <li>{@link #TONE_CDMA_CONFIRM}
+     * <li>{@link #TONE_CDMA_ANSWER}
+     * <li>{@link #TONE_CDMA_NETWORK_CALLWAITING}
+     * <li>{@link #TONE_CDMA_PIP}
+     * <li>{@link #TONE_CDMA_CALL_SIGNAL_ISDN_NORMAL}
+     * <li>{@link #TONE_CDMA_CALL_SIGNAL_ISDN_INTERGROUP}
+     * <li>{@link #TONE_CDMA_CALL_SIGNAL_ISDN_SP_PRI}
+     * <li>{@link #TONE_CDMA_CALL_SIGNAL_ISDN_PAT3}
+     * <li>{@link #TONE_CDMA_CALL_SIGNAL_ISDN_PING_RING}
+     * <li>{@link #TONE_CDMA_CALL_SIGNAL_ISDN_PAT5}
+     * <li>{@link #TONE_CDMA_CALL_SIGNAL_ISDN_PAT6}
+     * <li>{@link #TONE_CDMA_CALL_SIGNAL_ISDN_PAT7}
+     * <li>{@link #TONE_CDMA_HIGH_L}
+     * <li>{@link #TONE_CDMA_MED_L}
+     * <li>{@link #TONE_CDMA_LOW_L}
+     * <li>{@link #TONE_CDMA_HIGH_SS}
+     * <li>{@link #TONE_CDMA_MED_SS}
+     * <li>{@link #TONE_CDMA_LOW_SS}
+     * <li>{@link #TONE_CDMA_HIGH_SSL}
+     * <li>{@link #TONE_CDMA_MED_SSL}
+     * <li>{@link #TONE_CDMA_LOW_SSL}
+     * <li>{@link #TONE_CDMA_HIGH_SS_2}
+     * <li>{@link #TONE_CDMA_MED_SS_2}
+     * <li>{@link #TONE_CDMA_LOW_SS_2}
+     * <li>{@link #TONE_CDMA_HIGH_SLS}
+     * <li>{@link #TONE_CDMA_MED_SLS}
+     * <li>{@link #TONE_CDMA_LOW_SLS}
+     * <li>{@link #TONE_CDMA_HIGH_S_X4}
+     * <li>{@link #TONE_CDMA_MED_S_X4}
+     * <li>{@link #TONE_CDMA_LOW_S_X4}
+     * <li>{@link #TONE_CDMA_HIGH_PBX_L}
+     * <li>{@link #TONE_CDMA_MED_PBX_L}
+     * <li>{@link #TONE_CDMA_LOW_PBX_L}
+     * <li>{@link #TONE_CDMA_HIGH_PBX_SS}
+     * <li>{@link #TONE_CDMA_MED_PBX_SS}
+     * <li>{@link #TONE_CDMA_LOW_PBX_SS}
+     * <li>{@link #TONE_CDMA_HIGH_PBX_SSL}
+     * <li>{@link #TONE_CDMA_MED_PBX_SSL}
+     * <li>{@link #TONE_CDMA_LOW_PBX_SSL}
+     * <li>{@link #TONE_CDMA_HIGH_PBX_SLS}
+     * <li>{@link #TONE_CDMA_MED_PBX_SLS}
+     * <li>{@link #TONE_CDMA_LOW_PBX_SLS}
+     * <li>{@link #TONE_CDMA_HIGH_PBX_S_X4}
+     * <li>{@link #TONE_CDMA_MED_PBX_S_X4}
+     * <li>{@link #TONE_CDMA_LOW_PBX_S_X4}
+     * <li>{@link #TONE_CDMA_ALERT_NETWORK_LITE}
+     * <li>{@link #TONE_CDMA_ALERT_AUTOREDIAL_LITE}
+     * <li>{@link #TONE_CDMA_ONE_MIN_BEEP}
+     * <li>{@link #TONE_CDMA_KEYPAD_VOLUME_KEY_LITE}
+     * <li>{@link #TONE_CDMA_PRESSHOLDKEY_LITE}
+     * <li>{@link #TONE_CDMA_ALERT_INCALL_LITE}
+     * <li>{@link #TONE_CDMA_EMERGENCY_RINGBACK}
+     * <li>{@link #TONE_CDMA_ALERT_CALL_GUARD}
+     * <li>{@link #TONE_CDMA_SOFT_ERROR_LITE}
+     * <li>{@link #TONE_CDMA_CALLDROP_LITE}
+     * <li>{@link #TONE_CDMA_NETWORK_BUSY_ONE_SHOT}
+     * <li>{@link #TONE_CDMA_ABBR_ALERT}
+     * <li>{@link #TONE_CDMA_SIGNAL_OFF}
      * </ul>
      * @see #ToneGenerator(int, int)
     */
@@ -566,7 +863,7 @@
     private native final void native_setup(int streamType, int volume);
 
     private native final void native_finalize();
-    
+
     @Override
     protected void finalize() { native_finalize(); }
 
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index 9552aa6..f19649b 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -27,6 +27,7 @@
 
 LOCAL_C_INCLUDES += \
     external/tremor/Tremor \
+    frameworks/base/core/jni \
     $(PV_INCLUDES) \
     $(JNI_H_INCLUDE) \
     $(call include-path-for, corecg graphics)
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 6317fe2..2c08c16 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -20,6 +20,7 @@
 #include "utils/Log.h"
 
 #include <media/mediaplayer.h>
+#include <media/MediaPlayerInterface.h>
 #include <stdio.h>
 #include <assert.h>
 #include <limits.h>
@@ -30,6 +31,8 @@
 #include "JNIHelp.h"
 #include "android_runtime/AndroidRuntime.h"
 #include "utils/Errors.h"  // for status_t
+#include "android_util_Binder.h"
+#include <binder/Parcel.h>
 
 
 // ----------------------------------------------------------------------------
@@ -442,6 +445,28 @@
     return NULL;
 }
 
+
+// Sends the request and reply parcels to the media player via the
+// binder interface.
+static jint
+android_media_MediaPlayer_invoke(JNIEnv *env, jobject thiz,
+                                 jobject java_request, jobject java_reply)
+{
+    sp<MediaPlayer> media_player = getMediaPlayer(env, thiz);
+    if (media_player == NULL ) {
+        jniThrowException(env, "java/lang/IllegalStateException", NULL);
+    }
+
+
+    Parcel *request = parcelForJavaObject(env, java_request);
+    Parcel *reply = parcelForJavaObject(env, java_reply);
+
+    const status_t status = media_player->invoke(*request, reply);
+    // Don't use process_media_player_call which use the async loop to
+    // report errors, instead returns the status.
+    return status;
+}
+
 static void
 android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this)
 {
@@ -503,6 +528,7 @@
     {"isLooping",           "()Z",                              (void *)android_media_MediaPlayer_isLooping},
     {"setVolume",           "(FF)V",                            (void *)android_media_MediaPlayer_setVolume},
     {"getFrameAt",          "(I)Landroid/graphics/Bitmap;",     (void *)android_media_MediaPlayer_getFrameAt},
+    {"native_invoke",       "(Landroid/os/Parcel;Landroid/os/Parcel;)I",(void *)android_media_MediaPlayer_invoke},
     {"native_setup",        "(Ljava/lang/Object;)V",            (void *)android_media_MediaPlayer_native_setup},
     {"native_finalize",     "()V",                              (void *)android_media_MediaPlayer_native_finalize},
 };
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index 7bfeb83..0273a5a 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -41,7 +41,7 @@
 // ----------------------------------------------------------------------------
 
 // helper function to extract a native Camera object from a Camera Java object
-extern sp<Camera> get_native_camera(JNIEnv *env, jobject thiz, struct camera_context_t** context);
+extern sp<Camera> get_native_camera(JNIEnv *env, jobject thiz, struct JNICameraContext** context);
 
 struct fields_t {
     jfieldID    context;
diff --git a/media/libmedia/IMediaMetadataRetriever.cpp b/media/libmedia/IMediaMetadataRetriever.cpp
index d16394f..397a55b 100644
--- a/media/libmedia/IMediaMetadataRetriever.cpp
+++ b/media/libmedia/IMediaMetadataRetriever.cpp
@@ -126,7 +126,7 @@
     }
 };
 
-IMPLEMENT_META_INTERFACE(MediaMetadataRetriever, "android.hardware.IMediaMetadataRetriever");
+IMPLEMENT_META_INTERFACE(MediaMetadataRetriever, "android.media.IMediaMetadataRetriever");
 
 // ----------------------------------------------------------------------
 
@@ -209,4 +209,3 @@
 // ----------------------------------------------------------------------------
 
 }; // namespace android
-
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
index e1bed5f..3f278f4 100644
--- a/media/libmedia/IMediaPlayer.cpp
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -39,7 +39,8 @@
     RESET,
     SET_AUDIO_STREAM_TYPE,
     SET_LOOPING,
-    SET_VOLUME
+    SET_VOLUME,
+    INVOKE,
 };
 
 class BpMediaPlayer: public BpInterface<IMediaPlayer>
@@ -170,9 +171,16 @@
         remote()->transact(SET_VOLUME, data, &reply);
         return reply.readInt32();
     }
+
+    status_t invoke(const Parcel& request, Parcel *reply)
+    { // Avoid doing any extra copy. The interface descriptor should
+      // have been set by MediaPlayer.java.
+        status_t retcode = remote()->transact(INVOKE, request, reply);
+        return retcode;
+    }
 };
 
-IMPLEMENT_META_INTERFACE(MediaPlayer, "android.hardware.IMediaPlayer");
+IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer");
 
 // ----------------------------------------------------------------------
 
@@ -260,6 +268,11 @@
             reply->writeInt32(setVolume(data.readFloat(), data.readFloat()));
             return NO_ERROR;
         } break;
+        case INVOKE: {
+            CHECK_INTERFACE(IMediaPlayer, data, reply);
+            invoke(data, reply);
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
@@ -268,4 +281,3 @@
 // ----------------------------------------------------------------------------
 
 }; // namespace android
-
diff --git a/media/libmedia/IMediaPlayerClient.cpp b/media/libmedia/IMediaPlayerClient.cpp
index da4f7ef..bf51829 100644
--- a/media/libmedia/IMediaPlayerClient.cpp
+++ b/media/libmedia/IMediaPlayerClient.cpp
@@ -46,7 +46,7 @@
     }
 };
 
-IMPLEMENT_META_INTERFACE(MediaPlayerClient, "android.hardware.IMediaPlayerClient");
+IMPLEMENT_META_INTERFACE(MediaPlayerClient, "android.media.IMediaPlayerClient");
 
 // ----------------------------------------------------------------------
 
@@ -68,4 +68,3 @@
 }
 
 }; // namespace android
-
diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp
index a79d4f7..0f64259 100644
--- a/media/libmedia/IMediaPlayerService.cpp
+++ b/media/libmedia/IMediaPlayerService.cpp
@@ -20,6 +20,7 @@
 #include <binder/Parcel.h>
 
 #include <binder/IMemory.h>
+#include <utils/Errors.h>  // for status_t
 #include <media/IMediaPlayerService.h>
 #include <media/IMediaRecorder.h>
 
@@ -111,7 +112,7 @@
     }
 };
 
-IMPLEMENT_META_INTERFACE(MediaPlayerService, "android.hardware.IMediaPlayerService");
+IMPLEMENT_META_INTERFACE(MediaPlayerService, "android.media.IMediaPlayerService");
 
 // ----------------------------------------------------------------------
 
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index 53b5aa3..df7d301 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -264,7 +264,7 @@
     }
 };
 
-IMPLEMENT_META_INTERFACE(MediaRecorder, "android.hardware.IMediaRecorder");
+IMPLEMENT_META_INTERFACE(MediaRecorder, "android.media.IMediaRecorder");
 
 // ----------------------------------------------------------------------
 
diff --git a/media/libmedia/ToneGenerator.cpp b/media/libmedia/ToneGenerator.cpp
index 81ee92c..c22cd53 100644
--- a/media/libmedia/ToneGenerator.cpp
+++ b/media/libmedia/ToneGenerator.cpp
@@ -33,199 +33,720 @@
 
 // Descriptors for all available tones (See ToneGenerator::ToneDescriptor class declaration for details)
 const ToneGenerator::ToneDescriptor ToneGenerator::sToneDescriptors[] = {
-        { segments: {{ duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1336, 941, 0 }},
-                     { duration: 0 , waveFreq: { 0 }}},
+        { segments: {{ duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1336, 941, 0 }, 0, 0},
+                     { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 0 },                              // TONE_DTMF_0
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1209, 697, 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1209, 697, 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 0 },                              // TONE_DTMF_1
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1336, 697, 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1336, 697, 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 0 },                              // TONE_DTMF_2
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1477, 697, 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1477, 697, 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 0 },                              // TONE_DTMF_3
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1209, 770, 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1209, 770, 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 0 },                              // TONE_DTMF_4
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1336, 770, 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1336, 770, 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 0 },                              // TONE_DTMF_5
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1477, 770, 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1477, 770, 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 0 },                              // TONE_DTMF_6
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1209, 852, 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1209, 852, 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 0 },                              // TONE_DTMF_7
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1336, 852, 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1336, 852, 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 0 },                              // TONE_DTMF_8
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1477, 852, 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1477, 852, 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 0 },                              // TONE_DTMF_9
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1209, 941, 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1209, 941, 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 0 },                              // TONE_DTMF_S
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1477, 941, 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1477, 941, 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 0 },                              // TONE_DTMF_P
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1633, 697, 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1633, 697, 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 0 },                              // TONE_DTMF_A
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1633, 770, 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1633, 770, 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 0 },                             // TONE_DTMF_B
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1633, 852, 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1633, 852, 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 0 },                              // TONE_DTMF_C
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1633, 941, 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 1633, 941, 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 0 },                              // TONE_DTMF_D
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 425, 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 425, 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 0 },                              // TONE_SUP_DIAL
-        { segments: { { duration: 500 , waveFreq: { 425, 0 }},
-                      { duration: 500, waveFreq: { 0 }},
-                         { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: 500 , waveFreq: { 425, 0 }, 0, 0},
+                      { duration: 500, waveFreq: { 0 }, 0, 0},
+                         { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 0 },                              // TONE_SUP_BUSY
-        { segments: { { duration: 200, waveFreq: { 425, 0 } },
-                      { duration: 200, waveFreq: { 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: 200, waveFreq: { 425, 0 }, 0, 0 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 0 },                              // TONE_SUP_CONGESTION
-        { segments: { { duration: 200, waveFreq: { 425, 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: 200, waveFreq: { 425, 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: 0,
           repeatSegment: 0 },                              // TONE_SUP_RADIO_ACK
-        { segments: { { duration: 200, waveFreq: { 425, 0 }},
-                      { duration: 200, waveFreq: { 0 }},
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: 200, waveFreq: { 425, 0 }, 0, 0},
+                      { duration: 200, waveFreq: { 0 }, 0, 0},
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: 2,
           repeatSegment: 0 },                              // TONE_SUP_RADIO_NOTAVAIL
-        { segments: { { duration: 330, waveFreq: { 950, 1400, 1800, 0 }},
-                      { duration: 1000, waveFreq: { 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: 330, waveFreq: { 950, 1400, 1800, 0 }, 0, 0},
+                      { duration: 1000, waveFreq: { 0 }, 0, 0},
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 0 },                              // TONE_SUP_ERROR
-        { segments: { { duration: 200, waveFreq: { 425, 0 } },
-                      { duration: 600, waveFreq: { 0 } },
-                      { duration: 200, waveFreq: { 425, 0 } },
-                      { duration: 3000, waveFreq: { 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: 200, waveFreq: { 425, 0 }, 0, 0 },
+                      { duration: 600, waveFreq: { 0 }, 0, 0 },
+                      { duration: 200, waveFreq: { 425, 0 }, 0, 0 },
+                      { duration: 3000, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 0 },                              // TONE_SUP_CALL_WAITING
-        { segments: { { duration: 1000, waveFreq: { 425, 0 } },
-                      { duration: 4000, waveFreq: { 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: 1000, waveFreq: { 425, 0 }, 0, 0 },
+                      { duration: 4000, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 0 },                              // TONE_SUP_RINGTONE
-        { segments: { { duration: 40, waveFreq: { 400, 1200, 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: 40, waveFreq: { 400, 1200, 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: 0,
           repeatSegment: 0 },                              // TONE_PROP_BEEP
-        { segments: { { duration: 100, waveFreq: { 1200, 0 } },
-                      { duration: 100, waveFreq: { 0 }  },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: 100, waveFreq: { 1200, 0 }, 0, 0 },
+                      { duration: 100, waveFreq: { 0 }, 0, 0  },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: 1,
           repeatSegment: 0 },                              // TONE_PROP_ACK
-        { segments: { { duration: 400, waveFreq: { 300, 400, 500, 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: 400, waveFreq: { 300, 400, 500, 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: 0,
           repeatSegment: 0 },                              // TONE_PROP_NACK
-        { segments: { { duration: 200, waveFreq: { 400, 1200, 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: 200, waveFreq: { 400, 1200, 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: 0,
           repeatSegment: 0 },                              // TONE_PROP_PROMPT
-        { segments: { { duration: 40, waveFreq: { 400, 1200, 0 } },
-                      { duration: 200, waveFreq: { 0 } },
-                      { duration: 40, waveFreq: { 400, 1200, 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: 40, waveFreq: { 400, 1200, 0 }, 0, 0 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 40, waveFreq: { 400, 1200, 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: 0,
           repeatSegment: 0 },                             // TONE_PROP_BEEP2
-        { segments: { { duration: 250, waveFreq: { 440, 0 } },
-                      { duration: 250, waveFreq: { 620, 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: 250, waveFreq: { 440, 0 }, 0, 0 },
+                      { duration: 250, waveFreq: { 620, 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0 }},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 0 },                              // TONE_SUP_INTERCEPT
-        { segments: { { duration: 250, waveFreq: { 440, 0 } },
-                      { duration: 250, waveFreq: { 620, 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: 250, waveFreq: { 440, 0 }, 0, 0 },
+                      { duration: 250, waveFreq: { 620, 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: 7,
           repeatSegment: 0 },                             // TONE_SUP_INTERCEPT_ABBREV
-        { segments: { { duration: 250, waveFreq: { 480, 620, 0 } },
-                      { duration: 250, waveFreq: { 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: 250, waveFreq: { 480, 620, 0 }, 0, 0 },
+                      { duration: 250, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: 7,
           repeatSegment: 0 },                             // TONE_SUP_CONGESTION_ABBREV
-        { segments: { { duration: 100, waveFreq: { 350, 440, 0 } },
-                      { duration: 100, waveFreq: { 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: 100, waveFreq: { 350, 440, 0 }, 0, 0 },
+                      { duration: 100, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: 2,
           repeatSegment: 0 },                             // TONE_SUP_CONFIRM
-        { segments: { { duration: 100, waveFreq: { 480, 0 } },
-                      { duration: 100, waveFreq: { 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: 100, waveFreq: { 480, 0 }, 0, 0 },
+                      { duration: 100, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: 3,
           repeatSegment: 0 },                              // TONE_SUP_PIP
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 350, 440, 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: {{ duration: ToneGenerator::TONEGEN_INF, waveFreq: { 425, 0 }, 0, 0},
+                     { duration: 0 , waveFreq: { 0 }, 0, 0}},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                              // TONE_CDMA_DIAL_TONE_LITE
+        { segments: { { duration: 2000, waveFreq: { 440, 480, 0 }, 0, 0 },
+                      { duration: 4000, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                              // TONE_CDMA_NETWORK_USA_RINGBACK
+        { segments: { { duration: 250, waveFreq: { 440, 0 }, 0, 0 },
+                      { duration: 250, waveFreq: { 620, 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
+          repeatCnt:  ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                             // TONE_CDMA_INTERCEPT
+        { segments: { { duration: 250, waveFreq: { 440, 0 }, 0, 0 },
+                      { duration: 250, waveFreq: { 620, 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
+          repeatCnt:  0,
+          repeatSegment: 0 },                             // TONE_CDMA_ABBR_INTERCEPT
+        { segments: { { duration: 250, waveFreq: { 480, 620, 0 }, 0, 0 },
+                      { duration: 250, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                              // TONE_CDMA_REORDER
+        { segments: { { duration: 250, waveFreq: { 480, 620, 0 }, 0, 0 },
+                      { duration: 250, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
+          repeatCnt: 7,
+          repeatSegment: 0 },                              // TONE_CDMA_ABBR_REORDER
+        { segments: { { duration: 500, waveFreq: { 480, 620, 0 }, 0, 0 },
+                      { duration: 500, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                              // TONE_CDMA_NETWORK_BUSY
+        { segments: { { duration: 100, waveFreq: { 350, 440, 0 }, 0, 0 },
+                      { duration: 100, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
+          repeatCnt: 2,
+          repeatSegment: 0 },                              // TONE_CDMA_CONFIRM
+        { segments: { { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: 0,
+          repeatSegment: 0 },                              // TONE_CDMA_ANSWER
+        { segments: { { duration: 300, waveFreq: { 440, 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
+          repeatCnt: 0,
+          repeatSegment: 0 },                              // TONE_CDMA_NETWORK_CALLWAITING
+        { segments: { { duration: 100, waveFreq: { 480, 0 }, 0, 0 },
+                      { duration: 100, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
+          repeatCnt: 3,
+          repeatSegment: 0 },                              // TONE_CDMA_PIP
+
+        { segments: { { duration: 32, waveFreq: { 2091, 0}, 0, 0 },
+                      { duration: 64, waveFreq: { 2556, 0}, 19, 0},
+                      { duration: 32, waveFreq: { 2091, 0}, 0, 0},
+                      { duration: 48, waveFreq: { 2556, 0}, 0, 0},
+                      { duration: 4000, waveFreq: { 0 }, 0, 0},
+                      { duration: 0,  waveFreq: { 0 }, 0, 0}},
+          repeatCnt: 0,
+          repeatSegment: 0 },                             // TONE_CDMA_CALL_SIGNAL_ISDN_NORMAL
+        { segments: { { duration: 32, waveFreq: { 2091, 0}, 0, 0 },
+                      { duration: 64, waveFreq: { 2556, 0}, 7, 0 },
+                      { duration: 32, waveFreq: { 2091, 0}, 0, 0 },
+                      { duration: 400, waveFreq: { 0 }, 0, 0 },
+                      { duration: 32,  waveFreq: { 2091, 0}, 0, 0 },
+                      { duration: 64,  waveFreq: { 2556, 0}, 7, 4 },
+                      { duration: 32,  waveFreq: { 2091, 0}, 0, 0 },
+                      { duration: 4000, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0,    waveFreq: { 0 }, 0, 0 } },
+          repeatCnt: 0,
+          repeatSegment: 0 },                              // TONE_CDMA_CALL_SIGNAL_ISDN_INTERGROUP
+        { segments: { { duration: 32, waveFreq: { 2091, 0}, 0, 0 },
+                      { duration: 64, waveFreq: { 2556, 0}, 3, 0 },
+                      { duration: 16, waveFreq: { 2091, 0}, 0, 0 },
+                      { duration: 200, waveFreq: { 0 },     0, 0 },
+                      { duration: 32, waveFreq: { 2091, 0}, 0, 0 },
+                      { duration: 64, waveFreq: { 2556, 0}, 3, 4 },
+                      { duration: 16, waveFreq: { 2091, 0}, 0, 0 },
+                      { duration: 200, waveFreq: { 0 },     0, 0 },
+                      { duration: 0,   waveFreq: { 0 },     0, 0 } },
+          repeatCnt: 0,
+          repeatSegment: 0 },                            // TONE_CDMA_CALL_SIGNAL_ISDN_SP_PRI
+        { segments: { { duration: 0,  waveFreq: { 0 }, 0, 0} },
+           repeatCnt: 0,
+           repeatSegment: 0 },                            // TONE_CDMA_CALL_SIGNAL_ISDN_PAT3
+        { segments: { { duration: 32, waveFreq: { 2091, 0 }, 0, 0 },
+                      { duration: 64, waveFreq: { 2556, 0 }, 4, 0 },
+                      { duration: 20, waveFreq: { 2091, 0 }, 0, 0 },
+                      { duration: 0,  waveFreq: { 0 }      , 0, 0 } },
+          repeatCnt: 0,
+          repeatSegment: 0 },                             // TONE_CDMA_CALL_SIGNAL_ISDN_PING_RING
+        { segments: { { duration: 0,  waveFreq: { 0 }, 0, 0} },
+          repeatCnt: 0,
+          repeatSegment: 0 },                             // TONE_CDMA_CALL_SIGNAL_ISDN_PAT5
+        { segments: { { duration: 0,  waveFreq: { 0 }, 0, 0} },
+          repeatCnt: 0,
+          repeatSegment: 0 },                             // TONE_CDMA_CALL_SIGNAL_ISDN_PAT6
+        { segments: { { duration: 0,  waveFreq: { 0 }, 0, 0} },
+          repeatCnt: 0,
+          repeatSegment: 0 },                             // TONE_CDMA_CALL_SIGNAL_ISDN_PAT7
+
+        { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 4000, 0 }, 39, 0 },
+                      { duration: 4000, waveFreq: { 0 },     0, 0 },
+                      { duration: 0,    waveFreq: { 0 },     0, 0 } },
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_HIGH_L
+        { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2900, 0 }, 39, 0 },
+                      { duration: 4000, waveFreq: { 0 },     0, 0 },
+                      { duration: 0,    waveFreq: { 0 },     0, 0 } },
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_MED_L
+        { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1450, 0 }, 39, 0 },
+                      { duration: 4000, waveFreq: { 0 },     0, 0 },
+                      { duration: 0,    waveFreq: { 0 },     0, 0 } },
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_LOW_L
+        { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 4000, 0 }, 15, 0 },
+                      { duration: 400, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 } },
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_HIGH_SS
+        { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2900, 0 }, 15, 0 },
+                      { duration: 400, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_MED_SS
+        { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1450, 0 }, 15, 0 },
+                      { duration: 400, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_LOW_SS
+        { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 4000, 0 }, 7, 0 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 4000, 0 }, 7, 3 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 4000, 0 }, 15, 6 },
+                      { duration: 4000, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_HIGH_SSL
+        { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2900, 0 }, 7, 0 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2900, 0 }, 7, 3 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2900, 0 }, 15, 6 },
+                      { duration: 4000, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_MED_SSL
+        { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1450, 0 }, 7, 0 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1450, 0 }, 7, 3 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1450, 0 }, 15, 6 },
+                      { duration: 4000, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_LOW_SSL
+        { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 4000, 0 }, 19, 0 },
+                      { duration: 1000, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 4000, 0 }, 19, 3 },
+                      { duration: 3000, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_HIGH_SS_2
+        { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2900, 0 }, 19, 0 },
+                      { duration: 1000, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2900, 0 }, 19, 3 },
+                      { duration: 3000, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_MED_SS_2
+        { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1450, 0 }, 19, 0 },
+                      { duration: 1000, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1450, 0 }, 19, 3 },
+                      { duration: 3000, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_LOW_SS_2
+        { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 4000, 0 }, 9, 0 },
+                      { duration: 500, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 4000, 0 }, 19, 3 },
+                      { duration: 500, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 4000, 0 }, 9, 6 },
+                      { duration: 3000, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_HIGH_SLS
+        { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2900, 0 }, 9, 0 },
+                      { duration: 500, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2900, 0 }, 19, 3 },
+                      { duration: 500, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2900, 0 }, 9, 6 },
+                      { duration: 3000, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_MED_SLS
+        { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1450, 0 }, 9, 0 },
+                      { duration: 500, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1450, 0 }, 19, 3 },
+                      { duration: 500, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1450, 0 }, 9, 6 },
+                      { duration: 3000, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_LOW_SLS
+        { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 4000, 0 }, 9, 0 },
+                      { duration: 500, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 4000, 0 }, 9, 3 },
+                      { duration: 500, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 4000, 0 }, 9, 6 },
+                      { duration: 500, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 4000, 0 }, 9, 9 },
+                      { duration: 2500, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_HIGH_S_X4
+        { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2900, 0 }, 9, 0 },
+                      { duration: 500, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2900, 0 }, 9, 3 },
+                      { duration: 500, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2900, 0 }, 9, 6 },
+                      { duration: 500, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2900, 0 }, 9, 9 },
+                      { duration: 2500, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_MED_S_X4
+        { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1450, 0 }, 9, 0 },
+                      { duration: 500, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1450, 0 }, 9, 3 },
+                      { duration: 500, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1450, 0 }, 9, 6 },
+                      { duration: 500, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1450, 0 }, 9, 9 },
+                      { duration: 2500, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_LOW_S_X4
+        { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 4000, 0 }, 19, 0 },
+                      { duration: 2000, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_HIGH_PBX_L
+        { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2900, 0 }, 19, 0 },
+                      { duration: 2000, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_MED_PBX_L
+        { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1450, 0 }, 19, 0 },
+                      { duration: 2000, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_LOW_PBX_L
+        { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 4000, 0 }, 7, 0 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 4000, 0 }, 7, 3 },
+                      { duration: 2000, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_HIGH_PBX_SS
+        { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2900, 0 }, 7, 0 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2900, 0 }, 7, 3 },
+                      { duration: 2000, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_MED_PBX_SS
+        { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1450, 0 }, 7, 0 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1450, 0 }, 7, 3 },
+                      { duration: 2000, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_LOW_PBX_SS
+        { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 4000, 0 }, 7, 0 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 4000, 0 }, 7, 3 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 4000, 0 }, 15, 6 },
+                      { duration: 1000, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_HIGH_PBX_SSL
+        { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2900, 0 }, 7, 0 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2900, 0 }, 7, 3 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2900, 0 }, 15, 6 },
+                      { duration: 1000, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_MED_PBX_SSL
+        { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1450, 0 }, 7, 0 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1450, 0 }, 7, 3 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1450, 0 }, 15, 6 },
+                      { duration: 1000, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_LOW_PBX_SSL
+        { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 4000, 0 }, 7, 0 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 4000, 0 }, 15, 3 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 4000, 0 }, 7, 6 },
+                      { duration: 1000, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_HIGH_PBX_SLS
+        { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2900, 0 }, 7, 0 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2900, 0 }, 15, 3 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2900, 0 }, 7, 6 },
+                      { duration: 1000, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_MED_PBX_SLS
+        { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1450, 0 }, 7, 0 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1450, 0 }, 15, 3 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1450, 0 }, 7, 6 },
+                      { duration: 1000, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_LOW_PBX_SLS
+        { segments: { { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 4000, 0 }, 7, 0 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 4000, 0 }, 7, 3 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 4000, 0 }, 7, 6 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 3700, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 4000, 0 }, 7, 9 },
+                      { duration: 800, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_HIGH_PBX_S_X4
+        { segments: { { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2900, 0 }, 7, 0 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2900, 0 }, 7, 3 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2900, 0 }, 7, 6 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2600, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 2900, 0 }, 7, 9 },
+                      { duration: 800, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_MED_PBX_S_X4
+        { segments: { { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1450, 0 }, 7, 0 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1450, 0 }, 7, 3 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1450, 0 }, 7, 6 },
+                      { duration: 200, waveFreq: { 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1300, 0 }, 0, 0 },
+                      { duration: 25, waveFreq: { 1450, 0 }, 7, 9 },
+                      { duration: 800, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                           // TONE_CDMA_LOW_PBX_S_X4
+
+        { segments: { { duration: 62, waveFreq: { 1109, 0 }, 0, 0 },
+                      { duration: 62, waveFreq: { 784, 0 },  0, 0 },
+                      { duration: 62, waveFreq: { 740, 0 },  0, 0 },
+                      { duration: 62, waveFreq: { 622, 0 },  0, 0 },
+                      { duration: 62, waveFreq: { 1109, 0 }, 0, 0 },
+                      { duration: 0,  waveFreq: { 0 },       0, 0 } },
+          repeatCnt: 0,
+          repeatSegment: 0 },                            // TONE_CDMA_ALERT_NETWORK_LITE
+        { segments: { { duration: 62, waveFreq: { 1245, 0 }, 0, 0 },
+                      { duration: 62, waveFreq: { 659, 0 },  2, 0 },
+                      { duration: 62, waveFreq: { 1245, 0 }, 0, 0 },
+                      { duration: 0,  waveFreq: { 0 },       0, 0 } },
+          repeatCnt: 0,
+          repeatSegment: 0 },                            // TONE_CDMA_ALERT_AUTOREDIAL_LITE
+        { segments: { { duration: 400, waveFreq: { 1150, 770, 0 }, 0, 0 },
+                      { duration: 0,   waveFreq: { 0 },            0, 0 } },
+          repeatCnt: 0,
+          repeatSegment: 0 },                            // TONE_CDMA_ONE_MIN_BEEP
+        { segments: { { duration: 120, waveFreq: { 941, 1477, 0 }, 0, 0 },
+                      { duration: 0,   waveFreq: { 0 },            0, 0 } },
+          repeatCnt: 0,
+          repeatSegment: 0 },                            // TONE_CDMA_KEYPAD_VOLUME_KEY_LITE
+        { segments: { { duration: 375, waveFreq: { 587, 0 }, 0, 0 },
+                      { duration: 125, waveFreq: { 1175, 0 }, 0, 0 },
+                      { duration: 0,   waveFreq: { 0 },       0, 0 } },
+          repeatCnt: 0,
+          repeatSegment: 0 },                            // TONE_CDMA_PRESSHOLDKEY_LITE
+        { segments: { { duration: 62, waveFreq: { 587, 0 }, 0, 0 },
+                      { duration: 62, waveFreq: { 784, 0 }, 0, 0 },
+                      { duration: 62, waveFreq: { 831, 0 }, 0, 0 },
+                      { duration: 62, waveFreq: { 784, 0 }, 0, 0 },
+                      { duration: 62, waveFreq: { 1109, 0 }, 0, 0 },
+                      { duration: 62, waveFreq: { 784, 0 }, 0, 0 },
+                      { duration: 62, waveFreq: { 831, 0 }, 0, 0 },
+                      { duration: 62, waveFreq: { 784, 0 }, 0, 0 },
+                      { duration: 0,  waveFreq: { 0 },      0, 0 } },
+          repeatCnt: 0,
+          repeatSegment: 0 },                             // TONE_CDMA_ALERT_INCALL_LITE
+        { segments: { { duration: 125, waveFreq: { 941, 0 }, 0, 0 },
+                      { duration: 10,  waveFreq: { 0 },      2, 0 },
+                      { duration: 4990, waveFreq: { 0 },     0, 0 },
+                      { duration: 0,    waveFreq: { 0 },     0, 0 } },
+          repeatCnt: ToneGenerator::TONEGEN_INF,
+          repeatSegment: 0 },                            // TONE_CDMA_EMERGENCY_RINGBACK
+        { segments: { { duration: 125, waveFreq: { 1319, 0 }, 0, 0 },
+                      { duration: 125, waveFreq: { 0 },       0, 0 },
+                      { duration: 0,   waveFreq: { 0 },       0, 0 } },
+          repeatCnt: 2,
+          repeatSegment: 0 },                            // TONE_CDMA_ALERT_CALL_GUARD
+        { segments: { { duration: 125, waveFreq: { 1047, 0 }, 0, 0 },
+                      { duration: 125, waveFreq: { 370,  0 }, 0, 0 },
+                      { duration: 0,   waveFreq: { 0 },       0, 0 } },
+          repeatCnt: 0,
+          repeatSegment: 0 },                            // TONE_CDMA_SOFT_ERROR_LITE
+        { segments: { { duration: 125, waveFreq: { 1480, 0 }, 0, 0 },
+                      { duration: 125, waveFreq: { 1397, 0 }, 0, 0 },
+                      { duration: 125, waveFreq: { 784, 0 },  0, 0 },
+                      { duration: 0,   waveFreq: { 0 },       0, 0 } },
+          repeatCnt: 0,
+          repeatSegment: 0 },                            // TONE_CDMA_CALLDROP_LITE
+
+        { segments: { { duration: 500, waveFreq: { 425, 0 }, 0, 0 },
+                      { duration: 500, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: 0,
+          repeatSegment: 0 },                           // TONE_CDMA_NETWORK_BUSY_ONE_SHOT
+        { segments: { { duration: 400, waveFreq: { 1150, 770 }, 0, 0 },
+                      { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: 0,
+          repeatSegment: 0 },                           // TONE_CDMA_ABBR_ALERT
+          { segments: { { duration: 0, waveFreq: { 0 }, 0, 0 }},
+          repeatCnt: 0,
+          repeatSegment: 0 },                            // TONE_CDMA_SIGNAL_OFF
+
+        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 350, 440, 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 0 },                              // TONE_ANSI_DIAL
-        { segments: { { duration: 500, waveFreq: { 480, 620, 0 } },
-                      { duration: 500, waveFreq: { 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: 500, waveFreq: { 480, 620, 0 }, 0, 0 },
+                      { duration: 500, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 0 },                              // TONE_ANSI_BUSY
-        { segments: { { duration: 250, waveFreq: { 480, 620, 0 } },
-                      { duration: 250, waveFreq: { 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: 250, waveFreq: { 480, 620, 0 }, 0, 0 },
+                      { duration: 250, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 0 },                              // TONE_ANSI_CONGESTION
-        { segments: { { duration: 300, waveFreq: { 440, 0 } },
-                      { duration: 9700, waveFreq: { 0 } },
-                      { duration: 100, waveFreq: { 440, 0 } },
-                      { duration: 100, waveFreq: { 0 } },
-                      { duration: 100, waveFreq: { 440, 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: 300, waveFreq: { 440, 0 }, 0, 0 },
+                      { duration: 9700, waveFreq: { 0 }, 0, 0 },
+                      { duration: 100, waveFreq: { 440, 0 }, 0, 0 },
+                      { duration: 100, waveFreq: { 0 }, 0, 0 },
+                      { duration: 100, waveFreq: { 440, 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 1 },                              // TONE_ANSI_CALL_WAITING
-        { segments: { { duration: 2000, waveFreq: { 440, 480, 0 } },
-                      { duration: 4000, waveFreq: { 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: 2000, waveFreq: { 440, 480, 0 }, 0, 0 },
+                      { duration: 4000, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 0 },                              // TONE_ANSI_RINGTONE
-        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 400, 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: ToneGenerator::TONEGEN_INF, waveFreq: { 400, 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 0 },                              // TONE_JAPAN_DIAL
-        { segments: { { duration: 500, waveFreq: { 400, 0 } },
-                      { duration: 500, waveFreq: { 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: 500, waveFreq: { 400, 0 }, 0, 0 },
+                      { duration: 500, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 0 },                              // TONE_JAPAN_BUSY
-        { segments: { { duration: 1000, waveFreq: { 400, 0 } },
-                      { duration: 2000, waveFreq: { 0 } },
-                      { duration: 0 , waveFreq: { 0 }}},
+        { segments: { { duration: 1000, waveFreq: { 400, 0 }, 0, 0 },
+                      { duration: 2000, waveFreq: { 0 }, 0, 0 },
+                      { duration: 0 , waveFreq: { 0 }, 0, 0}},
           repeatCnt: ToneGenerator::TONEGEN_INF,
           repeatSegment: 0 },                              // TONE_JAPAN_RADIO_ACK
+
+
+
 };
 
 // Used by ToneGenerator::getToneForRegion() to convert user specified supervisory tone type
@@ -529,9 +1050,9 @@
 //
 ////////////////////////////////////////////////////////////////////////////////
 void ToneGenerator::audioCallback(int event, void* user, void *info) {
-    
+
     if (event != AudioTrack::EVENT_MORE_DATA) return;
-    
+
     const AudioTrack::Buffer *buffer = static_cast<const AudioTrack::Buffer *>(info);
     ToneGenerator *lpToneGen = static_cast<ToneGenerator *>(user);
     short *lpOut = buffer->i16;
@@ -549,12 +1070,12 @@
         unsigned int lGenSmp;
         unsigned int lWaveCmd = WaveGenerator::WAVEGEN_CONT;
         bool lSignal = false;
- 
+
         lpToneGen->mLock.lock();
 
         // Update pcm frame count and end time (current time at the end of this process)
         lpToneGen->mTotalSmp += lReqSmp;
-    
+
         // Update tone gen state machine and select wave gen command
         switch (lpToneGen->mState) {
         case TONE_PLAYING:
@@ -562,13 +1083,13 @@
             break;
         case TONE_STARTING:
             LOGV("Starting Cbk");
-    
+
             lWaveCmd = WaveGenerator::WAVEGEN_START;
             break;
         case TONE_STOPPING:
         case TONE_RESTARTING:
             LOGV("Stop/restart Cbk");
-    
+
             lWaveCmd = WaveGenerator::WAVEGEN_STOP;
             lpToneGen->mNextSegSmp = TONEGEN_INF; // forced to skip state machine management below
             break;
@@ -578,21 +1099,21 @@
             lNumSmp = 0;
             goto audioCallback_EndLoop;
         }
-        
-    
+
+
         // Exit if tone sequence is over
         if (lpToneDesc->segments[lpToneGen->mCurSegment].duration == 0) {
             if (lpToneGen->mState == TONE_PLAYING) {
-                lpToneGen->mState = TONE_STOPPING;            
+                lpToneGen->mState = TONE_STOPPING;
             }
             goto audioCallback_EndLoop;
         }
-    
+
         if (lpToneGen->mTotalSmp > lpToneGen->mNextSegSmp) {
             // Time to go to next sequence segment
-    
+
             LOGV("End Segment, time: %d\n", (unsigned int)(systemTime()/1000000));
-    
+
             lGenSmp = lReqSmp;
 
             // If segment,  ON -> OFF transition : ramp volume down
@@ -609,25 +1130,49 @@
                 LOGV("ON->OFF, lGenSmp: %d, lReqSmp: %d\n", lGenSmp, lReqSmp);
             }
 
-            // Go to next segment
-            lpToneGen->mCurSegment++;
+            // check if we need to loop and loop for the reqd times
+            if (lpToneDesc->segments[lpToneGen->mCurSegment].loopCnt) {
+                if (lpToneGen->mLoopCounter < lpToneDesc->segments[lpToneGen->mCurSegment].loopCnt) {
+                    LOGV ("in if loop loopCnt(%d) loopctr(%d), CurSeg(%d) \n",
+                          lpToneDesc->segments[lpToneGen->mCurSegment].loopCnt,
+                          lpToneGen->mLoopCounter,
+                          lpToneGen->mCurSegment);
+                    lpToneGen->mCurSegment = lpToneDesc->segments[lpToneGen->mCurSegment].loopIndx;
+                    ++lpToneGen->mLoopCounter;
+                } else {
+                    // completed loop. go to next segment
+                    lpToneGen->mLoopCounter = 0;
+                    lpToneGen->mCurSegment++;
+                    LOGV ("in else loop loopCnt(%d) loopctr(%d), CurSeg(%d) \n",
+                          lpToneDesc->segments[lpToneGen->mCurSegment].loopCnt,
+                          lpToneGen->mLoopCounter,
+                          lpToneGen->mCurSegment);
+                }
+            } else {
+                lpToneGen->mCurSegment++;
+                LOGV ("Goto next seg loopCnt(%d) loopctr(%d), CurSeg(%d) \n",
+                      lpToneDesc->segments[lpToneGen->mCurSegment].loopCnt,
+                      lpToneGen->mLoopCounter,
+                      lpToneGen->mCurSegment);
+
+            }
 
             // Handle loop if last segment reached
             if (lpToneDesc->segments[lpToneGen->mCurSegment].duration == 0) {
                 LOGV("Last Seg: %d\n", lpToneGen->mCurSegment);
-    
+
                 // Pre increment loop count and restart if total count not reached. Stop sequence otherwise
                 if (++lpToneGen->mCurCount <= lpToneDesc->repeatCnt) {
                     LOGV("Repeating Count: %d\n", lpToneGen->mCurCount);
-    
+
                     lpToneGen->mCurSegment = lpToneDesc->repeatSegment;
                     if (lpToneDesc->segments[lpToneDesc->repeatSegment].waveFreq[0] != 0) {
                         lWaveCmd = WaveGenerator::WAVEGEN_START;
                     }
-    
+
                     LOGV("New segment %d, Next Time: %d\n", lpToneGen->mCurSegment,
                             (lpToneGen->mNextSegSmp*1000)/lpToneGen->mSamplingRate);
-    
+
                 } else {
                     lGenSmp = 0;
                     LOGV("End repeat, time: %d\n", (unsigned int)(systemTime()/1000000));
@@ -644,11 +1189,11 @@
                     lGenSmp = 0;
                 }
             }
-    
+
             // Update next segment transition position. No harm to do it also for last segment as lpToneGen->mNextSegSmp won't be used any more
             lpToneGen->mNextSegSmp
                     += (lpToneDesc->segments[lpToneGen->mCurSegment].duration * lpToneGen->mSamplingRate) / 1000;
-    
+
         } else {
             // Inside a segment keep tone ON or OFF
             if (lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[0] == 0) {
@@ -657,24 +1202,24 @@
                 lGenSmp = lReqSmp;  // If event segment, tone is currently ON
             }
         }
-    
+
         if (lGenSmp) {
             // If samples must be generated, call all active wave generators and acumulate waves in lpOut
             unsigned int lFreqIdx = 0;
             unsigned short lFrequency = lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[lFreqIdx];
-    
+
             while (lFrequency != 0) {
                 WaveGenerator *lpWaveGen = lpToneGen->mWaveGens.valueFor(lFrequency);
                 lpWaveGen->getSamples(lpOut, lGenSmp, lWaveCmd);
                 lFrequency = lpToneDesc->segments[lpToneGen->mCurSegment].waveFreq[++lFreqIdx];
             }
         }
-        
+
         lNumSmp -= lReqSmp;
         lpOut += lReqSmp;
-    
+
 audioCallback_EndLoop:
-    
+
         switch (lpToneGen->mState) {
         case TONE_RESTARTING:
             LOGV("Cbk restarting track\n");
@@ -694,7 +1239,7 @@
             LOGV("Cbk Stopping track\n");
             lSignal = true;
             lpToneGen->mpAudioTrack->stop();
-            
+
             // Force loop exit
             lNumSmp = 0;
             break;
@@ -765,6 +1310,7 @@
     mTotalSmp = 0;
     mCurSegment = 0;
     mCurCount = 0;
+    mLoopCounter = 0;
     if (mpToneDesc->segments[0].duration == TONEGEN_INF) {
         mNextSegSmp = TONEGEN_INF;
     } else{
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 220c998..4683166 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -196,6 +196,20 @@
     return err;
 }
 
+status_t MediaPlayer::invoke(const Parcel& request, Parcel *reply)
+{
+    Mutex::Autolock _l(mLock);
+    if ((mPlayer != NULL) && ( mCurrentState & MEDIA_PLAYER_INITIALIZED ))
+    {
+         LOGV("invoke %d", request.dataSize());
+         return  mPlayer->invoke(request, reply);
+    }
+    LOGE("invoke failed: wrong state %X", mCurrentState);
+    return INVALID_OPERATION;
+}
+
+
+
 status_t MediaPlayer::setVideoSurface(const sp<Surface>& surface)
 {
     LOGV("setVideoSurface");
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 8ac697e..c4dccdf 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -39,6 +39,10 @@
 #include <binder/IServiceManager.h>
 #include <binder/MemoryHeapBase.h>
 #include <binder/MemoryBase.h>
+#include <utils/Errors.h>  // for status_t
+#include <utils/String8.h>
+#include <utils/Vector.h>
+#include <cutils/properties.h>
 
 #include <media/MediaPlayerInterface.h>
 #include <media/mediarecorder.h>
@@ -65,7 +69,6 @@
 #undef __KERNEL__
 #endif
 
-
 namespace android {
 
 // TODO: Temp hack until we can register players
@@ -675,6 +678,14 @@
     return p->setVideoSurface(surface);
 }
 
+status_t MediaPlayerService::Client::invoke(const Parcel& request,
+                                            Parcel *reply)
+{
+    sp<MediaPlayerBase> p = getPlayer();
+    if (p == NULL) return UNKNOWN_ERROR;
+    return p->invoke(request, reply);
+}
+
 status_t MediaPlayerService::Client::prepareAsync()
 {
     LOGV("[%d] prepareAsync", mConnId);
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 5a296bf..12f2231 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -187,6 +187,7 @@
         virtual status_t        setAudioStreamType(int type);
         virtual status_t        setLooping(int loop);
         virtual status_t        setVolume(float leftVolume, float rightVolume);
+        virtual status_t        invoke(const Parcel& request, Parcel *reply);
 
         sp<MediaPlayerBase>     createPlayer(player_type playerType);
                 status_t        setDataSource(const char *url);
@@ -238,4 +239,3 @@
 }; // namespace android
 
 #endif // ANDROID_MEDIAPLAYERSERVICE_H
-
diff --git a/media/libmediaplayerservice/MidiFile.h b/media/libmediaplayerservice/MidiFile.h
index 302f1cf..83d97fe 100644
--- a/media/libmediaplayerservice/MidiFile.h
+++ b/media/libmediaplayerservice/MidiFile.h
@@ -46,6 +46,7 @@
     virtual status_t    reset();
     virtual status_t    setLooping(int loop);
     virtual player_type playerType() { return SONIVOX_PLAYER; }
+    virtual status_t    invoke(const Parcel& request, Parcel *reply) {return INVALID_OPERATION;}
 
 private:
             status_t    createOutputTrack();
@@ -74,4 +75,3 @@
 }; // namespace android
 
 #endif // ANDROID_MIDIFILE_H
-
diff --git a/media/libmediaplayerservice/VorbisPlayer.h b/media/libmediaplayerservice/VorbisPlayer.h
index c30dc1b..4024654 100644
--- a/media/libmediaplayerservice/VorbisPlayer.h
+++ b/media/libmediaplayerservice/VorbisPlayer.h
@@ -53,6 +53,7 @@
     virtual status_t    reset();
     virtual status_t    setLooping(int loop);
     virtual player_type playerType() { return VORBIS_PLAYER; }
+    virtual status_t    invoke(const Parcel& request, Parcel *reply) {return INVALID_OPERATION;}
 
 private:
             status_t    setdatasource(const char *path, int fd, int64_t offset, int64_t length);
@@ -88,4 +89,3 @@
 }; // namespace android
 
 #endif // ANDROID_VORBISPLAYER_H
-
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
index 1b98f75..4adb04e 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java
@@ -54,20 +54,9 @@
     private static final int NUM_STRESS_LOOP = 10;
     private static final int NUM_PLAYBACk_IN_EACH_LOOP = 20;
     private static final long MEDIA_STRESS_WAIT_TIME = 5000; //5 seconds
-    private static final String H263_VIDEO_PLAYBACK_MEMOUT =
-        "/sdcard/h263VideoPlaybackMemOut.txt";
-    private static final String H264_VIDEO_PLAYBACK_MEMOUT =
-        "/sdcard/h264VideoPlaybackMemOut.txt";
-    private static final String WMV_VIDEO_PLAYBACK_MEMOUT =
-        "/sdcard/WmvVideoPlaybackMemOut.txt";
-    private static final String H263_VIDEO_ONLY_RECORD_MEMOUT =
-        "/sdcard/recordH263VideoOnlyMemOut.txt";
-    private static final String MP4_VIDEO_ONLY_RECORD_MEMOUT =
-        "/sdcard/recordMPEG4VideoOnlyMemOut.txt";
-    private static final String H263_VIDEO_AUDIO_RECORD_MEMOUT =
-        "/sdcard/recordVideoH263AudioMemOut.txt";
-    private static final String AUDIO_ONLY_RECORD_MEMOUT =
-        "/sdcard/recordAudioOnlyMemOut.txt";
+    private static final String MEDIA_MEMORY_OUTPUT =
+        "/sdcard/mediaMemOutput.txt";
+
     //the tolerant memory leak
     private static final int MAX_ACCEPTED_MEMORY_LEAK_KB = 150;
 
@@ -318,13 +307,18 @@
         return vsizevalue;
     }
 
-    public boolean validateMemoryResult(int startPid, int startMemory){
+    public boolean validateMemoryResult (int startPid, int startMemory, Writer output) throws Exception {
         mEndPid = getMediaserverPid();
         mEndMemory = getMediaserverVsize();
 
+        //Write the total memory different into the output file
+        output.write("The total diff = " + (mEndMemory - startMemory));
+        output.write("\n\n");
         //mediaserver crash
-        if (startPid != mEndPid)
+        if (startPid != mEndPid){
+            output.write("mediaserver died. Test failed\n");
             return false;
+        }
         //memory leak greter than the tolerant
         if ((mEndMemory - startMemory) > MAX_ACCEPTED_MEMORY_LEAK_KB )
             return false;
@@ -345,15 +339,17 @@
         mStartPid = getMediaserverPid();
         mStartMemory = getMediaserverVsize();
 
-        File h263MemoryOut = new File(H263_VIDEO_PLAYBACK_MEMOUT);
-        Writer output = new BufferedWriter(new FileWriter(h263MemoryOut));
+        File h263MemoryOut = new File(MEDIA_MEMORY_OUTPUT);
+        Writer output = new BufferedWriter(new FileWriter(h263MemoryOut, true));
+        output.write("H263 Video Playback Only\n");
         getMemoryWriteToLog(output);
         for (int i = 0; i < NUM_STRESS_LOOP; i++) {
             mediaStressPlayback(MediaNames.VIDEO_HIGHRES_H263);
             getMemoryWriteToLog(output);
         }
+        output.write("\n");
+        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output);
         output.close();
-        memoryResult = validateMemoryResult(mStartPid, mStartMemory);
         assertTrue("H263 playback memory test", memoryResult);
     }
 
@@ -364,15 +360,17 @@
         mStartPid = getMediaserverPid();
         mStartMemory = getMediaserverVsize();
 
-        File h264MemoryOut = new File(H264_VIDEO_PLAYBACK_MEMOUT);
-        Writer output = new BufferedWriter(new FileWriter(h264MemoryOut));
+        File h264MemoryOut = new File(MEDIA_MEMORY_OUTPUT);
+        Writer output = new BufferedWriter(new FileWriter(h264MemoryOut, true));
+        output.write("H264 Video Playback only\n");
         getMemoryWriteToLog(output);
         for (int i = 0; i < NUM_STRESS_LOOP; i++) {
             mediaStressPlayback(MediaNames.VIDEO_H264_AMR);
             getMemoryWriteToLog(output);
         }
+        output.write("\n");
+        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output);
         output.close();
-        memoryResult = validateMemoryResult(mStartPid, mStartMemory);
         assertTrue("H264 playback memory test", memoryResult);
     }
 
@@ -383,15 +381,17 @@
         mStartPid = getMediaserverPid();
         mStartMemory = getMediaserverVsize();
 
-        File wmvMemoryOut = new File(WMV_VIDEO_PLAYBACK_MEMOUT);
-        Writer output = new BufferedWriter(new FileWriter(wmvMemoryOut));
+        File wmvMemoryOut = new File(MEDIA_MEMORY_OUTPUT);
+        Writer output = new BufferedWriter(new FileWriter(wmvMemoryOut, true));
+        output.write("WMV video playback only\n");
         getMemoryWriteToLog(output);
         for (int i = 0; i < NUM_STRESS_LOOP; i++) {
             mediaStressPlayback(MediaNames.VIDEO_WMV);
             getMemoryWriteToLog(output);
         }
+        output.write("\n");
+        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output);
         output.close();
-        memoryResult = validateMemoryResult(mStartPid, mStartMemory);
         assertTrue("wmv playback memory test", memoryResult);
     }
 
@@ -402,16 +402,18 @@
         mStartPid = getMediaserverPid();
         mStartMemory = getMediaserverVsize();
 
-        File videoH263RecordOnlyMemoryOut = new File(H263_VIDEO_ONLY_RECORD_MEMOUT);
-        Writer output = new BufferedWriter(new FileWriter(videoH263RecordOnlyMemoryOut));
+        File videoH263RecordOnlyMemoryOut = new File(MEDIA_MEMORY_OUTPUT);
+        Writer output = new BufferedWriter(new FileWriter(videoH263RecordOnlyMemoryOut, true));
+        output.write("H263 video record only\n");
         getMemoryWriteToLog(output);
         for (int i = 0; i < NUM_STRESS_LOOP; i++) {
             stressVideoRecord(20, 352, 288, MediaRecorder.VideoEncoder.H263,
                     MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, true);
             getMemoryWriteToLog(output);
         }
+        output.write("\n");
+        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output);
         output.close();
-        memoryResult = validateMemoryResult(mStartPid, mStartMemory);
         assertTrue("H263 record only memory test", memoryResult);
     }
 
@@ -422,16 +424,18 @@
         mStartPid = getMediaserverPid();
         mStartMemory = getMediaserverVsize();
 
-        File videoMp4RecordOnlyMemoryOut = new File(MP4_VIDEO_ONLY_RECORD_MEMOUT);
-        Writer output = new BufferedWriter(new FileWriter(videoMp4RecordOnlyMemoryOut));
+        File videoMp4RecordOnlyMemoryOut = new File(MEDIA_MEMORY_OUTPUT);
+        Writer output = new BufferedWriter(new FileWriter(videoMp4RecordOnlyMemoryOut, true));
+        output.write("MPEG4 video record only\n");
         getMemoryWriteToLog(output);
         for (int i = 0; i < NUM_STRESS_LOOP; i++) {
             stressVideoRecord(20, 352, 288, MediaRecorder.VideoEncoder.MPEG_4_SP,
                     MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, true);
             getMemoryWriteToLog(output);
         }
+        output.write("\n");
+        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output);
         output.close();
-        memoryResult = validateMemoryResult(mStartPid, mStartMemory);
         assertTrue("mpeg4 record only memory test", memoryResult);
     }
 
@@ -443,16 +447,18 @@
         mStartPid = getMediaserverPid();
         mStartMemory = getMediaserverVsize();
 
-        File videoRecordAudioMemoryOut = new File(H263_VIDEO_AUDIO_RECORD_MEMOUT);
-        Writer output = new BufferedWriter(new FileWriter(videoRecordAudioMemoryOut));
+        File videoRecordAudioMemoryOut = new File(MEDIA_MEMORY_OUTPUT);
+        Writer output = new BufferedWriter(new FileWriter(videoRecordAudioMemoryOut, true));
+        output.write("Audio and h263 video record\n");
         getMemoryWriteToLog(output);
         for (int i = 0; i < NUM_STRESS_LOOP; i++) {
             stressVideoRecord(20, 352, 288, MediaRecorder.VideoEncoder.H263,
                     MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, false);
             getMemoryWriteToLog(output);
         }
+        output.write("\n");
+        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output);
         output.close();
-        memoryResult = validateMemoryResult(mStartPid, mStartMemory);
         assertTrue("H263 audio video record memory test", memoryResult);
     }
 
@@ -463,15 +469,17 @@
         mStartPid = getMediaserverPid();
         mStartMemory = getMediaserverVsize();
 
-        File audioOnlyMemoryOut = new File(AUDIO_ONLY_RECORD_MEMOUT);
-        Writer output = new BufferedWriter(new FileWriter(audioOnlyMemoryOut));
+        File audioOnlyMemoryOut = new File(MEDIA_MEMORY_OUTPUT);
+        Writer output = new BufferedWriter(new FileWriter(audioOnlyMemoryOut, true));
+        output.write("Audio record only\n");
         getMemoryWriteToLog(output);
         for (int i = 0; i < NUM_STRESS_LOOP; i++) {
             stressAudioRecord(MediaNames.RECORDER_OUTPUT);
             getMemoryWriteToLog(output);
         }
+        output.write("\n");
+        memoryResult = validateMemoryResult(mStartPid, mStartMemory, output);
         output.close();
-        memoryResult = validateMemoryResult(mStartPid, mStartMemory);
         assertTrue("audio record only memory test", memoryResult);
     }
 }
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java
index dbf937c..69e93a1 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/MediaRecorderStressTest.java
@@ -18,6 +18,11 @@
 
 import com.android.mediaframeworktest.MediaFrameworkTest;
 
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.Writer;
+
 import android.hardware.Camera;
 import android.media.MediaPlayer;
 import android.media.MediaRecorder;
@@ -47,6 +52,8 @@
     private static final long WAIT_TIME_PLAYBACK = 60000;  // 6 second
     private static final String OUTPUT_FILE = "/sdcard/temp";
     private static final String OUTPUT_FILE_EXT = ".3gp";
+    private static final String MEDIA_STRESS_OUTPUT =
+        "/sdcard/mediaStressOutput.txt";
     
     public MediaRecorderStressTest() {
         super("com.android.mediaframeworktest", MediaFrameworkTest.class);
@@ -62,8 +69,14 @@
     public void testStressCamera() throws Exception {
         SurfaceHolder mSurfaceHolder;             
         mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+        File stressOutFile = new File(MEDIA_STRESS_OUTPUT);
+        Writer output = new BufferedWriter(new FileWriter(stressOutFile, true));
+        output.write("Camera start preview stress:\n");
+        output.write("Total number of loops:" + 
+                NUMBER_OF_CAMERA_STRESS_LOOPS + "\n");
         try {        
             Log.v(TAG, "Start preview");
+            output.write("No of loop: ");
             for (int i = 0; i< NUMBER_OF_CAMERA_STRESS_LOOPS; i++){
                 mCamera = Camera.open();
                 mCamera.setPreviewDisplay(mSurfaceHolder);
@@ -71,10 +84,13 @@
                 Thread.sleep(WAIT_TIME_CAMERA_TEST);
                 mCamera.stopPreview();
                 mCamera.release();
+                output.write(" ," + i);
             }
         } catch (Exception e) {
                 Log.v(TAG, e.toString());
         }
+        output.write("\n\n");
+        output.close();
     }
     
     //Test case for stressing the camera preview.
@@ -83,7 +99,13 @@
         String filename;
         SurfaceHolder mSurfaceHolder;             
         mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
-        try {    
+        File stressOutFile = new File(MEDIA_STRESS_OUTPUT);
+        Writer output = new BufferedWriter(new FileWriter(stressOutFile, true));
+        output.write("H263 video record- reset after prepare Stress test\n");
+        output.write("Total number of loops:" +
+                NUMBER_OF_RECORDER_STRESS_LOOPS + "\n");
+        try {
+            output.write("No of loop: ");
             Log.v(TAG, "Start preview");
             for (int i = 0; i < NUMBER_OF_RECORDER_STRESS_LOOPS; i++){
                 Log.v(TAG, "counter = " + i);
@@ -106,10 +128,13 @@
                 Thread.sleep(WAIT_TIME_RECORDER_TEST);  
                 mRecorder.reset();
                 mRecorder.release();
+                output.write(", " + i);
             }
         } catch (Exception e) {
                 Log.v(TAG, e.toString());
         }
+        output.write("\n\n");
+        output.close();
     }
     
     
@@ -119,8 +144,14 @@
         String filename;
         SurfaceHolder mSurfaceHolder;             
         mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
+        File stressOutFile = new File(MEDIA_STRESS_OUTPUT);
+        Writer output = new BufferedWriter(new FileWriter(stressOutFile, true));
+        output.write("Camera and video recorder preview switching\n");
+        output.write("Total number of loops:"
+                + NUMBER_OF_SWTICHING_LOOPS_BW_CAMERA_AND_RECORDER + "\n");
         try {    
             Log.v(TAG, "Start preview");
+            output.write("No of loop: ");
             for (int i = 0; i < NUMBER_OF_SWTICHING_LOOPS_BW_CAMERA_AND_RECORDER; i++){
                 mCamera = Camera.open();
                 mCamera.setPreviewDisplay(mSurfaceHolder);
@@ -147,11 +178,14 @@
                 Log.v(TAG, "before release");
                 Thread.sleep(WAIT_TIME_CAMERA_TEST);  
                 mRecorder.release();
-                Log.v(TAG, "release video recorder");                
+                Log.v(TAG, "release video recorder");
+                output.write(", " + i);
             }
         } catch (Exception e) {
                 Log.v(TAG, e.toString());
         }
+        output.write("\n\n");
+        output.close();
     }
     
     //Stress test case for record a video and play right away.
@@ -160,7 +194,13 @@
         String filename;
         SurfaceHolder mSurfaceHolder;             
         mSurfaceHolder = MediaFrameworkTest.mSurfaceView.getHolder();
-        try {    
+        File stressOutFile = new File(MEDIA_STRESS_OUTPUT);
+        Writer output = new BufferedWriter(new FileWriter(stressOutFile, true));
+        output.write("Video record and play back stress test:\n");
+        output.write("Total number of loops:"
+                + NUMBER_OF_RECORDERANDPLAY_STRESS_LOOPS + "\n");
+        try {
+            output.write("No of loop: ");
             for (int i = 0; i < NUMBER_OF_RECORDERANDPLAY_STRESS_LOOPS; i++){
                 filename = OUTPUT_FILE + i + OUTPUT_FILE_EXT;
                 Log.v(TAG, filename);
@@ -189,10 +229,13 @@
                 mp.start();
                 Thread.sleep(WAIT_TIME_PLAYBACK);
                 mp.release();
+                output.write(", " + i);
             }
         } catch (Exception e) {
                 Log.v(TAG, e.toString());
         }
+        output.write("\n\n");
+        output.close();
     }   
 }
 
diff --git a/opengl/libagl/texture.cpp b/opengl/libagl/texture.cpp
index 05fd46e..d767c31 100644
--- a/opengl/libagl/texture.cpp
+++ b/opengl/libagl/texture.cpp
@@ -997,7 +997,7 @@
         memcpy(textureObject->crop_rect, params, 4*sizeof(GLint));
         break;
     default:
-        ogles_error(c, GL_INVALID_ENUM);
+        texParameterx(target, pname, GLfixed(params[0]), c);
         return;
     }
 }
@@ -1016,6 +1016,13 @@
     texParameterx(target, pname, param, c);
 }
 
+void glTexParameteri(
+        GLenum target, GLenum pname, GLint param)
+{
+    ogles_context_t* c = ogles_context_t::get();
+    texParameterx(target, pname, GLfixed(param), c);
+}
+
 // ----------------------------------------------------------------------------
 #if 0
 #pragma mark -
diff --git a/opengl/tests/angeles/Android.mk b/opengl/tests/angeles/Android.mk
index 46958d3..e193483 100644
--- a/opengl/tests/angeles/Android.mk
+++ b/opengl/tests/angeles/Android.mk
@@ -5,7 +5,7 @@
 LOCAL_SRC_FILES:= app-linux.c demo.c.arm
 LOCAL_SHARED_LIBRARIES := libEGL libGLESv1_CM libui
 LOCAL_MODULE:= angeles
-LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE_TAGS := optional
 include $(BUILD_EXECUTABLE)
 
 
@@ -13,5 +13,5 @@
 LOCAL_SRC_FILES:= gpustate.c
 LOCAL_SHARED_LIBRARIES := libEGL libGLESv1_CM
 LOCAL_MODULE:= gpustate
-LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE_TAGS := optional
 include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/filter/Android.mk b/opengl/tests/filter/Android.mk
index a448f0d..31b7d9a 100644
--- a/opengl/tests/filter/Android.mk
+++ b/opengl/tests/filter/Android.mk
@@ -12,6 +12,6 @@
 
 LOCAL_MODULE:= test-opengl-filter
 
-LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE_TAGS := optional
 
 include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/finish/Android.mk b/opengl/tests/finish/Android.mk
index 26836c1..8b46cd7 100644
--- a/opengl/tests/finish/Android.mk
+++ b/opengl/tests/finish/Android.mk
@@ -12,6 +12,6 @@
 
 LOCAL_MODULE:= test-opengl-finish
 
-LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE_TAGS := optional
 
 include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/textures/Android.mk b/opengl/tests/textures/Android.mk
index a8c6220..8d5f56d 100644
--- a/opengl/tests/textures/Android.mk
+++ b/opengl/tests/textures/Android.mk
@@ -12,6 +12,6 @@
 
 LOCAL_MODULE:= test-opengl-textures
 
-LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE_TAGS := optional
 
 include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/tritex/Android.mk b/opengl/tests/tritex/Android.mk
index 5cd1f04..76fd8dd 100644
--- a/opengl/tests/tritex/Android.mk
+++ b/opengl/tests/tritex/Android.mk
@@ -12,6 +12,6 @@
 
 LOCAL_MODULE:= test-opengl-tritex
 
-LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE_TAGS := optional
 
 include $(BUILD_EXECUTABLE)
diff --git a/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsIntentService.java b/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsIntentService.java
index 9992420..3cd2cc4 100644
--- a/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsIntentService.java
+++ b/packages/SubscribedFeedsProvider/src/com/android/providers/subscribedfeeds/SubscribedFeedsIntentService.java
@@ -16,9 +16,7 @@
 import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.os.Bundle;
-import android.os.RemoteException;
 import android.text.TextUtils;
-import android.net.Uri;
 import android.accounts.Account;
 
 import java.util.ArrayList;
@@ -113,8 +111,9 @@
                 + "and " + SubscribedFeeds.Feeds.FEED + "= ?";
         try {
             // TODO(fredq) fix the hardcoded type
+            final Account account = new Account(accountName, "com.google.GAIA");
             c = context.getContentResolver().query(SubscribedFeeds.Feeds.CONTENT_URI,
-                    null, where, new String[]{accountName, "com.google.GAIA", feed}, null);
+                    null, where, new String[]{account.mName, account.mType, feed}, null);
             if (c.getCount() == 0) {
                 Log.w(TAG, "received tickle for non-existent feed: "
                         + "account " + accountName + ", feed " + feed);
@@ -125,22 +124,14 @@
                 String authority = c.getString(c.getColumnIndexOrThrow(
                         SubscribedFeeds.Feeds.AUTHORITY));
                 EventLog.writeEvent(LOG_TICKLE, authority);
-                try {
-                    if (!ContentResolver.getContentService()
-                            .getSyncProviderAutomatically(authority)) {
-                        Log.d(TAG, "supressing tickle since provider " + authority
-                                + " is configured to not sync automatically");
-                        continue;
-                    }
-                } catch (RemoteException e) {
+                if (!ContentResolver.getSyncAutomatically(account, authority)) {
+                    Log.d(TAG, "supressing tickle since provider " + authority
+                            + " is configured to not sync automatically");
                     continue;
                 }
-                Uri uri = Uri.parse("content://" + authority);
                 Bundle extras = new Bundle();
-                extras.putParcelable(ContentResolver.SYNC_EXTRAS_ACCOUNT,
-                        new Account(accountName, "com.google.GAIA"));
                 extras.putString("feed", feed);
-                context.getContentResolver().startSync(uri, extras);
+                ContentResolver.requestSync(account, authority, extras);
             }
         } finally {
             if (c != null) c.deactivate();
diff --git a/packages/TtsService/jni/android_tts_SynthProxy.cpp b/packages/TtsService/jni/android_tts_SynthProxy.cpp
index 54d038a..0dafcc1 100644
--- a/packages/TtsService/jni/android_tts_SynthProxy.cpp
+++ b/packages/TtsService/jni/android_tts_SynthProxy.cpp
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
+#define LOG_NDEBUG 0
 
 #include <stdio.h>
 #include <unistd.h>
@@ -168,7 +168,7 @@
 static tts_callback_status ttsSynthDoneCB(void *& userdata, uint32_t rate,
                            AudioSystem::audio_format format, int channel,
                            int8_t *&wav, size_t &bufferSize, tts_synth_status status) {
-    LOGI("ttsSynthDoneCallback: %d bytes", bufferSize);
+    LOGV("ttsSynthDoneCallback: %d bytes", bufferSize);
 
     if (userdata == NULL){
         LOGE("userdata == NULL");
@@ -178,7 +178,7 @@
     SynthProxyJniStorage* pJniData = (SynthProxyJniStorage*)(pForAfter->jniStorage);
 
     if (pForAfter->usageMode == USAGEMODE_PLAY_IMMEDIATELY){
-        LOGI("Direct speech");
+        LOGV("Direct speech");
 
         if (wav == NULL) {
             delete pForAfter;
@@ -189,16 +189,16 @@
             prepAudioTrack(pJniData, rate, format, channel);
             if (pJniData->mAudioOut) {
                 pJniData->mAudioOut->write(wav, bufferSize);
-                LOGI("AudioTrack wrote: %d bytes", bufferSize);
+                //LOGV("AudioTrack wrote: %d bytes", bufferSize);
             } else {
-                LOGI("Can't play, null audiotrack");
+                LOGE("Can't play, null audiotrack");
             }
         }
     } else  if (pForAfter->usageMode == USAGEMODE_WRITE_TO_FILE) {
-        LOGI("Save to file");
+        LOGV("Save to file");
         if (wav == NULL) {
             delete pForAfter;
-            LOGI("Null: speech has completed");
+            LOGV("Null: speech has completed");
         }
         if (bufferSize > 0){
             fwrite(wav, 1, bufferSize, pForAfter->outputFile);
@@ -296,7 +296,7 @@
 
 static void
 android_tts_SynthProxy_setSpeechRate(JNIEnv *env, jobject thiz, jint jniData,
-        int speechRate)
+        jint speechRate)
 {
     if (jniData == 0) {
         LOGE("android_tts_SynthProxy_setSpeechRate(): invalid JNI data");
@@ -316,6 +316,28 @@
 }
 
 
+static void
+android_tts_SynthProxy_setPitch(JNIEnv *env, jobject thiz, jint jniData,
+        jint pitch)
+{
+    if (jniData == 0) {
+        LOGE("android_tts_SynthProxy_setPitch(): invalid JNI data");
+        return;
+    }
+
+    int bufSize = 10;
+    char buffer [bufSize];
+    sprintf(buffer, "%d", pitch);
+
+    SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
+    LOGI("setting pitch to %d", pitch);
+    // TODO check return codes
+    if (pSynthData->mNativeSynthInterface) {
+        pSynthData->mNativeSynthInterface->setProperty("pitch", buffer, bufSize);
+    }
+}
+
+
 // TODO: Refactor this to get rid of any assumptions about sample rate, etc.
 static void
 android_tts_SynthProxy_synthesizeToFile(JNIEnv *env, jobject thiz, jint jniData,
@@ -541,6 +563,10 @@
         "(II)V",
         (void*)android_tts_SynthProxy_setSpeechRate
     },
+    {   "native_setPitch",
+        "(II)V",
+        (void*)android_tts_SynthProxy_setPitch
+    },
     {   "native_playAudioBuffer",
         "(III)V",
         (void*)android_tts_SynthProxy_playAudioBuffer
diff --git a/packages/TtsService/src/android/tts/SynthProxy.java b/packages/TtsService/src/android/tts/SynthProxy.java
index 364dc58..3bdff37 100755
--- a/packages/TtsService/src/android/tts/SynthProxy.java
+++ b/packages/TtsService/src/android/tts/SynthProxy.java
@@ -81,6 +81,12 @@
         native_setSpeechRate(mJniData, speechRate);
     }
 
+    /**
+     * Sets the pitch of the synthesized voice
+     */
+    public final void setPitch(int pitch) {
+        native_setPitch(mJniData, pitch);
+    }
 
     /**
      * Plays the given audio buffer
@@ -145,6 +151,8 @@
             String variant);
 
     private native final void native_setSpeechRate(int jniData, int speechRate);
+    
+    private native final void native_setPitch(int jniData, int speechRate);
 
     // TODO add buffer format
     private native final void native_playAudioBuffer(int jniData, int bufferPointer, int bufferSize);
diff --git a/packages/TtsService/src/android/tts/TtsService.java b/packages/TtsService/src/android/tts/TtsService.java
index e9c4ab7..6fa3141 100755
--- a/packages/TtsService/src/android/tts/TtsService.java
+++ b/packages/TtsService/src/android/tts/TtsService.java
@@ -152,7 +152,6 @@
         // speech rate
         setSpeechRate(getDefaultRate());
 
-        // TODO handle default pitch
     }
 
 
@@ -171,6 +170,39 @@
     }
 
 
+    private String getDefaultLanguage() {
+        String defaultLang = android.provider.Settings.Secure.getString(mResolver,
+                android.provider.Settings.Secure.TTS_DEFAULT_LANG);
+        if (defaultLang == null) {
+            return TextToSpeech.Engine.FALLBACK_TTS_DEFAULT_LANG;
+        } else {
+            return defaultLang;
+        }
+    }
+
+
+    private String getDefaultCountry() {
+        String defaultCountry = android.provider.Settings.Secure.getString(mResolver,
+                android.provider.Settings.Secure.TTS_DEFAULT_COUNTRY);
+        if (defaultCountry == null) {
+            return TextToSpeech.Engine.FALLBACK_TTS_DEFAULT_COUNTRY;
+        } else {
+            return defaultCountry;
+        }
+    }
+
+
+    private String getDefaultLocVariant() {
+        String defaultVar = android.provider.Settings.Secure.getString(mResolver,
+                android.provider.Settings.Secure.TTS_DEFAULT_VARIANT);
+        if (defaultVar == null) {
+            return TextToSpeech.Engine.FALLBACK_TTS_DEFAULT_VARIANT;
+        } else {
+            return defaultVar;
+        }
+    }
+
+
     private void setSpeechRate(int rate) {
         if (isDefaultEnforced()) {
             nativeSynth.setSpeechRate(getDefaultRate());
@@ -179,16 +211,23 @@
         }
     }
 
+
+    private void setPitch(int pitch) {
+        nativeSynth.setPitch(pitch);
+    }
+
+
     private void setLanguage(String lang, String country, String variant) {
-        Log.v("TTS", "TtsService.setLanguage("+lang+", "+country+", "+variant+")");
+        Log.v("TTS", "TtsService.setLanguage(" + lang + ", " + country + ", " + variant + ")");
         if (isDefaultEnforced()) {
-            nativeSynth.setLanguage(lang, country, variant);
+            nativeSynth.setLanguage(getDefaultLanguage(), getDefaultCountry(),
+                    getDefaultLocVariant());
         } else {
-            // TODO handle default language
-            nativeSynth.setLanguage("eng", "USA", "");
+            nativeSynth.setLanguage(lang, country, variant);
         }
     }
 
+
     /**
      * Adds a sound resource to the TTS.
      *
@@ -363,6 +402,7 @@
                     if (synthAvailable) {
                         synthesizerLock.unlock();
                     }
+                    processSpeechQueue();
                 }
             }
         }
@@ -706,6 +746,17 @@
         }
 
         /**
+         * Sets the pitch for the TTS. Note that this will only have an
+         * effect on synthesized speech; it will not affect pre-recorded speech.
+         *
+         * @param pitch
+         *            The pitch that should be used for the synthesized voice
+         */
+        public void setPitch(int pitch) {
+            mSelf.setPitch(pitch);
+        }
+
+        /**
          * Sets the speech rate for the TTS, which affects the synthesized voice.
          *
          * @param lang  the three letter ISO language code.
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 75e0e64..fdd4617b 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -34,6 +34,7 @@
 import android.content.pm.Signature;
 import android.net.Uri;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Environment;
 import android.os.Handler;
@@ -164,8 +165,8 @@
         // Set up our transport options and initialize the default transport
         // TODO: Have transports register themselves somehow?
         // TODO: Don't create transports that we don't need to?
-        //mTransportId = BackupManager.TRANSPORT_LOCAL;
-        mTransportId = BackupManager.TRANSPORT_GOOGLE;
+        mTransportId = BackupManager.TRANSPORT_LOCAL;
+        //mTransportId = BackupManager.TRANSPORT_GOOGLE;
         mLocalTransport = new LocalTransport(context);  // This is actually pretty cheap
         mGoogleTransport = null;
 
@@ -350,28 +351,28 @@
     void addPackageParticipantsLocked(String packageName) {
         // Look for apps that define the android:backupAgent attribute
         if (DEBUG) Log.v(TAG, "addPackageParticipantsLocked: " + packageName);
-        List<ApplicationInfo> targetApps = allAgentApps();
+        List<PackageInfo> targetApps = allAgentPackages();
         addPackageParticipantsLockedInner(packageName, targetApps);
     }
 
     private void addPackageParticipantsLockedInner(String packageName,
-            List<ApplicationInfo> targetApps) {
+            List<PackageInfo> targetPkgs) {
         if (DEBUG) {
-            Log.v(TAG, "Adding " + targetApps.size() + " backup participants:");
-            for (ApplicationInfo a : targetApps) {
-                Log.v(TAG, "    " + a + " agent=" + a.backupAgentName);
+            Log.v(TAG, "Adding " + targetPkgs.size() + " backup participants:");
+            for (PackageInfo p : targetPkgs) {
+                Log.v(TAG, "    " + p + " agent=" + p.applicationInfo.backupAgentName);
             }
         }
 
-        for (ApplicationInfo app : targetApps) {
-            if (packageName == null || app.packageName.equals(packageName)) {
-                int uid = app.uid;
+        for (PackageInfo pkg : targetPkgs) {
+            if (packageName == null || pkg.packageName.equals(packageName)) {
+                int uid = pkg.applicationInfo.uid;
                 HashSet<ApplicationInfo> set = mBackupParticipants.get(uid);
                 if (set == null) {
                     set = new HashSet<ApplicationInfo>();
                     mBackupParticipants.put(uid, set);
                 }
-                set.add(app);
+                set.add(pkg.applicationInfo);
                 backUpPackageManagerData();
             }
         }
@@ -381,67 +382,67 @@
     // 'packageName' is null, *all* participating apps will be removed.
     void removePackageParticipantsLocked(String packageName) {
         if (DEBUG) Log.v(TAG, "removePackageParticipantsLocked: " + packageName);
-        List<ApplicationInfo> allApps = null;
+        List<PackageInfo> allApps = null;
         if (packageName != null) {
-            allApps = new ArrayList<ApplicationInfo>();
+            allApps = new ArrayList<PackageInfo>();
             try {
-                ApplicationInfo app = mPackageManager.getApplicationInfo(packageName, 0);
-                allApps.add(app);
+                int flags = PackageManager.GET_SIGNATURES;
+                allApps.add(mPackageManager.getPackageInfo(packageName, flags));
             } catch (Exception e) {
-                // just skip it
+                // just skip it (???)
             }
         } else {
             // all apps with agents
-            allApps = allAgentApps();
+            allApps = allAgentPackages();
         }
         removePackageParticipantsLockedInner(packageName, allApps);
     }
 
     private void removePackageParticipantsLockedInner(String packageName,
-            List<ApplicationInfo> agents) {
+            List<PackageInfo> agents) {
         if (DEBUG) {
             Log.v(TAG, "removePackageParticipantsLockedInner (" + packageName
                     + ") removing " + agents.size() + " entries");
-            for (ApplicationInfo a : agents) {
-                Log.v(TAG, "    - " + a);
+            for (PackageInfo p : agents) {
+                Log.v(TAG, "    - " + p);
             }
         }
-        for (ApplicationInfo app : agents) {
-            if (packageName == null || app.packageName.equals(packageName)) {
-                int uid = app.uid;
+        for (PackageInfo pkg : agents) {
+            if (packageName == null || pkg.packageName.equals(packageName)) {
+                int uid = pkg.applicationInfo.uid;
                 HashSet<ApplicationInfo> set = mBackupParticipants.get(uid);
                 if (set != null) {
                     // Find the existing entry with the same package name, and remove it.
                     // We can't just remove(app) because the instances are different.
                     for (ApplicationInfo entry: set) {
-                        if (entry.packageName.equals(app.packageName)) {
+                        if (entry.packageName.equals(pkg.packageName)) {
                             set.remove(entry);
                             backUpPackageManagerData();
                             break;
                         }
                     }
                     if (set.size() == 0) {
-                        mBackupParticipants.delete(uid);                    }
+                        mBackupParticipants.delete(uid);
+                    }
                 }
             }
         }
     }
 
     // Returns the set of all applications that define an android:backupAgent attribute
-    private List<ApplicationInfo> allAgentApps() {
+    private List<PackageInfo> allAgentPackages() {
         // !!! TODO: cache this and regenerate only when necessary
-        List<ApplicationInfo> allApps = mPackageManager.getInstalledApplications(0);
-        int N = allApps.size();
-        if (N > 0) {
-            for (int a = N-1; a >= 0; a--) {
-                ApplicationInfo app = allApps.get(a);
-                if (((app.flags&ApplicationInfo.FLAG_ALLOW_BACKUP) == 0)
-                        || app.backupAgentName == null) {
-                    allApps.remove(a);
-                }
+        int flags = PackageManager.GET_SIGNATURES;
+        List<PackageInfo> packages = mPackageManager.getInstalledPackages(flags);
+        int N = packages.size();
+        for (int a = N-1; a >= 0; a--) {
+            ApplicationInfo app = packages.get(a).applicationInfo;
+            if (((app.flags&ApplicationInfo.FLAG_ALLOW_BACKUP) == 0)
+                    || app.backupAgentName == null) {
+                packages.remove(a);
             }
         }
-        return allApps;
+        return packages;
     }
 
     // Reset the given package's known backup participants.  Unlike add/remove, the update
@@ -454,7 +455,7 @@
         if (DEBUG) Log.v(TAG, "updatePackageParticipantsLocked: " + packageName);
 
         // brute force but small code size
-        List<ApplicationInfo> allApps = allAgentApps();
+        List<PackageInfo> allApps = allAgentPackages();
         removePackageParticipantsLockedInner(packageName, allApps);
         addPackageParticipantsLockedInner(packageName, allApps);
     }
@@ -577,17 +578,7 @@
         public void run() {
             if (DEBUG) Log.v(TAG, "Beginning backup of " + mQueue.size() + " targets");
 
-            // start up the transport
-            try {
-                mTransport.startSession();
-            } catch (Exception e) {
-                Log.e(TAG, "Error session transport");
-                e.printStackTrace();
-                return;
-            }
-
-            // The transport is up and running.  First, back up the package manager
-            // metadata if necessary
+            // First, back up the package manager metadata if necessary
             boolean doPackageManager;
             synchronized (BackupManagerService.this) {
                 doPackageManager = mDoPackageManager;
@@ -600,7 +591,7 @@
                 if (DEBUG) Log.i(TAG, "Running PM backup pass as well");
 
                 PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent(
-                        mPackageManager, allAgentApps());
+                        mPackageManager, allAgentPackages());
                 BackupRequest pmRequest = new BackupRequest(new ApplicationInfo(), false);
                 pmRequest.appInfo.packageName = PACKAGE_MANAGER_SENTINEL;
                 processOneBackup(pmRequest,
@@ -613,10 +604,12 @@
 
             // Finally, tear down the transport
             try {
-                mTransport.endSession();
-            } catch (Exception e) {
-                Log.e(TAG, "Error ending transport");
-                e.printStackTrace();
+                if (!mTransport.finishBackup()) {
+                    // STOPSHIP TODO: handle errors
+                    Log.e(TAG, "Backup failure in finishBackup()");
+                }
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error in finishBackup()", e);
             }
 
             if (!mJournal.delete()) {
@@ -711,24 +704,18 @@
                     if (DEBUG) Log.v(TAG, "doBackup() success; calling transport");
                     backupData =
                         ParcelFileDescriptor.open(backupDataName, ParcelFileDescriptor.MODE_READ_ONLY);
-                    int error = transport.performBackup(packInfo, backupData);
+                    if (!transport.performBackup(packInfo, backupData)) {
+                        // STOPSHIP TODO: handle errors
+                        Log.e(TAG, "Backup failure in performBackup()");
+                    }
 
                     // !!! TODO: After successful transport, delete the now-stale data
                     // and juggle the files so that next time the new state is passed
                     //backupDataName.delete();
                     newStateName.renameTo(savedStateName);
                 }
-            } catch (NameNotFoundException e) {
-                Log.e(TAG, "Package not found on backup: " + packageName);
-            } catch (FileNotFoundException fnf) {
-                Log.w(TAG, "File not found on backup: ");
-                fnf.printStackTrace();
-            } catch (RemoteException e) {
-                Log.d(TAG, "Remote target " + request.appInfo.packageName + " threw during backup:");
-                e.printStackTrace();
             } catch (Exception e) {
-                Log.w(TAG, "Final exception guard in backup: ");
-                e.printStackTrace();
+                Log.e(TAG, "Error backing up " + packageName, e);
             }
         }
     }
@@ -736,25 +723,6 @@
 
     // ----- Restore handling -----
 
-    // Is the given package restorable on this device?  Returns the on-device app's
-    // ApplicationInfo struct if it is; null if not.
-    //
-    // !!! TODO: also consider signatures
-    PackageInfo isRestorable(PackageInfo packageInfo) {
-        if (packageInfo.packageName != null) {
-            try {
-                PackageInfo app = mPackageManager.getPackageInfo(packageInfo.packageName,
-                        PackageManager.GET_SIGNATURES);
-                if ((app.applicationInfo.flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0) {
-                    return app;
-                }
-            } catch (Exception e) {
-                // doesn't exist on this device, or other error -- just ignore it.
-            }
-        }
-        return null;
-    }
-
     private boolean signaturesMatch(Signature[] storedSigs, Signature[] deviceSigs) {
         // Allow unsigned apps, but not signed on one device and unsigned on the other
         // !!! TODO: is this the right policy?
@@ -794,6 +762,16 @@
         private int mToken;
         private RestoreSet mImage;
 
+        class RestoreRequest {
+            public PackageInfo app;
+            public int storedAppVersion;
+
+            RestoreRequest(PackageInfo _app, int _version) {
+                app = _app;
+                storedAppVersion = _version;
+            }
+        }
+
         PerformRestoreThread(IBackupTransport transport, int restoreSetToken) {
             mTransport = transport;
             mToken = restoreSetToken;
@@ -805,117 +783,141 @@
             /**
              * Restore sequence:
              *
-             * 1. start up the transport session
-             * 2. get the restore set description for our identity
-             * 3. for each app in the restore set:
+             * 1. get the restore set description for our identity
+             * 2. for each app in the restore set:
              *    3.a. if it's restorable on this device, add it to the restore queue
-             * 4. for each app in the restore queue:
-             *    4.a. clear the app data
-             *    4.b. get the restore data for the app from the transport
-             *    4.c. launch the backup agent for the app
-             *    4.d. agent.doRestore() with the data from the server
-             *    4.e. unbind the agent [and kill the app?]
-             * 5. shut down the transport
+             * 3. for each app in the restore queue:
+             *    3.a. clear the app data
+             *    3.b. get the restore data for the app from the transport
+             *    3.c. launch the backup agent for the app
+             *    3.d. agent.doRestore() with the data from the server
+             *    3.e. unbind the agent [and kill the app?]
+             * 4. shut down the transport
              */
 
-            int err = -1;
+            // build the set of apps to restore
             try {
-                err = mTransport.startSession();
-            } catch (Exception e) {
-                Log.e(TAG, "Error starting transport for restore");
-                e.printStackTrace();
-            }
+                RestoreSet[] images = mTransport.getAvailableRestoreSets();
+                if (images == null) {
+                    // STOPSHIP TODO: Handle the failure somehow?
+                    Log.e(TAG, "Error getting restore sets");
+                    return;
+                }
 
-            if (err == 0) {
-                // build the set of apps to restore
-                try {
-                    RestoreSet[] images = mTransport.getAvailableRestoreSets();
-                    if (images.length > 0) {
-                        // !!! TODO: pick out the set for this token
-                        mImage = images[0];
+                if (images.length == 0) {
+                    Log.i(TAG, "No restore sets available");
+                    return;
+                }
 
-                        // Pull the Package Manager metadata from the restore set first
-                        PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent(
-                                mPackageManager, allAgentApps());
-                        PackageInfo pmApp = new PackageInfo();
-                        pmApp.packageName = PACKAGE_MANAGER_SENTINEL;
-                        processOneRestore(pmApp, IBackupAgent.Stub.asInterface(pmAgent.onBind()));
+                mImage = images[0];
 
-                        // build the set of apps we will attempt to restore
-                        PackageInfo[] packages = mTransport.getAppSet(mImage.token);
-                        HashSet<PackageInfo> appsToRestore = new HashSet<PackageInfo>();
-                        for (PackageInfo pkg: packages) {
-                            // get the real PackageManager idea of the package
-                            PackageInfo app = isRestorable(pkg);
-                            if (app != null) {
-                                // Validate against the backed-up signature block, too
-                                Metadata info = pmAgent.getRestoredMetadata(app.packageName);
-                                if (app.versionCode >= info.versionCode) {
-                                    if (DEBUG) Log.v(TAG, "Restore version " + info.versionCode
-                                            + " compatible with app version " + app.versionCode);
-                                    if (signaturesMatch(info.signatures, app.signatures)) {
-                                        appsToRestore.add(app);
-                                    } else {
-                                        Log.w(TAG, "Sig mismatch restoring " + app.packageName);
-                                    }
-                                } else {
-                                    Log.i(TAG, "Restore set for " + app.packageName
-                                            + " is too new [" + info.versionCode
-                                            + "] for installed app version " + app.versionCode);
-                                }
-                            }
-                        }
+                // Get the list of all packages which have backup enabled.
+                // (Include the Package Manager metadata pseudo-package first.)
+                ArrayList<PackageInfo> restorePackages = new ArrayList<PackageInfo>();
+                PackageInfo omPackage = new PackageInfo();
+                omPackage.packageName = PACKAGE_MANAGER_SENTINEL;
+                restorePackages.add(omPackage);
 
-                        // now run the restore queue
-                        doQueuedRestores(appsToRestore);
+                List<PackageInfo> agentPackages = allAgentPackages();
+                restorePackages.addAll(agentPackages);
+
+                // STOPSHIP TODO: pick out the set for this token (instead of images[0])
+                long token = images[0].token;
+                if (!mTransport.startRestore(token, restorePackages.toArray(new PackageInfo[0]))) {
+                    // STOPSHIP TODO: Handle the failure somehow?
+                    Log.e(TAG, "Error starting restore operation");
+                    return;
+                }
+
+                String packageName = mTransport.nextRestorePackage();
+                if (packageName == null) {
+                    // STOPSHIP TODO: Handle the failure somehow?
+                    Log.e(TAG, "Error getting first restore package");
+                    return;
+                } else if (packageName.equals("")) {
+                    Log.i(TAG, "No restore data available");
+                    return;
+                } else if (!packageName.equals(PACKAGE_MANAGER_SENTINEL)) {
+                    Log.e(TAG, "Expected restore data for \"" + PACKAGE_MANAGER_SENTINEL
+                          + "\", found only \"" + packageName + "\"");
+                    return;
+                }
+
+                // Pull the Package Manager metadata from the restore set first
+                PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent(
+                        mPackageManager, agentPackages);
+                processOneRestore(omPackage, 0, IBackupAgent.Stub.asInterface(pmAgent.onBind()));
+
+                for (;;) {
+                    packageName = mTransport.nextRestorePackage();
+                    if (packageName == null) {
+                        // STOPSHIP TODO: Handle the failure somehow?
+                        Log.e(TAG, "Error getting next restore package");
+                        return;
+                    } else if (packageName.equals("")) {
+                        break;
                     }
-                } catch (RemoteException e) {
-                    // can't happen; transports run locally
-                }
 
-                // done; shut down the transport
-                try {
-                    mTransport.endSession();
-                } catch (Exception e) {
-                    Log.e(TAG, "Error ending transport for restore");
-                    e.printStackTrace();
-                }
-            }
+                    Metadata metaInfo = pmAgent.getRestoredMetadata(packageName);
+                    if (metaInfo == null) {
+                        Log.e(TAG, "Missing metadata for " + packageName);
+                        continue;
+                    }
 
-            // even if the initial session startup failed, report that we're done here
-        }
+                    int flags = PackageManager.GET_SIGNATURES;
+                    PackageInfo packageInfo = mPackageManager.getPackageInfo(packageName, flags);
+                    if (metaInfo.versionCode > packageInfo.versionCode) {
+                        Log.w(TAG, "Package " + packageName
+                                + " restore version [" + metaInfo.versionCode
+                                + "] is too new for installed version ["
+                                + packageInfo.versionCode + "]");
+                        continue;
+                    }
 
-        // restore each app in the queue
-        void doQueuedRestores(HashSet<PackageInfo> appsToRestore) {
-            for (PackageInfo app : appsToRestore) {
-                Log.d(TAG, "starting agent for restore of " + app);
+                    if (!signaturesMatch(metaInfo.signatures, packageInfo.signatures)) {
+                        Log.w(TAG, "Signature mismatch restoring " + packageName);
+                        continue;
+                    }
 
-                try {
-                    // Remove the app's data first
-                    clearApplicationDataSynchronous(app.packageName);
+                    if (DEBUG) Log.v(TAG, "Package " + packageName
+                            + " restore version [" + metaInfo.versionCode
+                            + "] is compatible with installed version ["
+                            + packageInfo.versionCode + "]");
 
-                    // Now perform the restore into the clean app
-                    IBackupAgent agent = bindToAgentSynchronous(app.applicationInfo,
+                    // Now perform the actual restore
+                    clearApplicationDataSynchronous(packageName);
+                    IBackupAgent agent = bindToAgentSynchronous(
+                            packageInfo.applicationInfo,
                             IApplicationThread.BACKUP_MODE_RESTORE);
-                    if (agent != null) {
-                        processOneRestore(app, agent);
+                    if (agent == null) {
+                        Log.w(TAG, "Can't find backup agent for " + packageName);
+                        continue;
                     }
 
-                    // unbind even on timeout, just in case
-                    mActivityManager.unbindBackupAgent(app.applicationInfo);
-                } catch (SecurityException ex) {
-                    // Try for the next one.
-                    Log.d(TAG, "error in bind", ex);
-                } catch (RemoteException e) {
-                    // can't happen
+                    try {
+                        processOneRestore(packageInfo, metaInfo.versionCode, agent);
+                    } finally {
+                        // unbind even on timeout or failure, just in case
+                        mActivityManager.unbindBackupAgent(packageInfo.applicationInfo);
+                    }
                 }
-
+            } catch (NameNotFoundException e) {
+                // STOPSHIP TODO: Handle the failure somehow?
+                Log.e(TAG, "Invalid paackage restoring data", e);
+            } catch (RemoteException e) {
+                // STOPSHIP TODO: Handle the failure somehow?
+                Log.e(TAG, "Error restoring data", e);
+            } finally {
+                try {
+                    mTransport.finishRestore();
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Error finishing restore", e);
+                }
             }
         }
 
-        // Do the guts of a restore of one application, derived from the 'mImage'
-        // restore set via the 'mTransport' transport.
-        void processOneRestore(PackageInfo app, IBackupAgent agent) {
+        // Do the guts of a restore of one application, using mTransport.getRestoreData().
+        void processOneRestore(PackageInfo app, int appVersionCode, IBackupAgent agent) {
             // !!! TODO: actually run the restore through mTransport
             final String packageName = app.packageName;
 
@@ -930,11 +932,12 @@
 
                 // Run the transport's restore pass
                 // Run the target's backup pass
-                int err = -1;
                 try {
-                    err = mTransport.getRestoreData(mImage.token, app, backupData);
-                } catch (RemoteException e) {
-                    // can't happen
+                    if (!mTransport.getRestoreData(backupData)) {
+                        // STOPSHIP TODO: Handle this error somehow?
+                        Log.e(TAG, "Error getting restore data for " + packageName);
+                        return;
+                    }
                 } finally {
                     backupData.close();
                 }
@@ -949,30 +952,18 @@
                 backupData = ParcelFileDescriptor.open(backupDataName,
                             ParcelFileDescriptor.MODE_READ_ONLY);
 
-                boolean success = false;
                 try {
-                    agent.doRestore(backupData, newState);
-                    success = true;
-                } catch (Exception e) {
-                    Log.e(TAG, "Restore failed for " + packageName);
-                    e.printStackTrace();
+                    agent.doRestore(backupData, appVersionCode, newState);
                 } finally {
                     newState.close();
                     backupData.close();
                 }
 
                 // if everything went okay, remember the recorded state now
-                if (success) {
-                    File savedStateName = new File(mStateDir, packageName);
-                    newStateName.renameTo(savedStateName);
-                }
-            } catch (FileNotFoundException fnfe) {
-                Log.v(TAG, "Couldn't open file for restore: " + fnfe);
-            } catch (IOException ioe) {
-                Log.e(TAG, "Unable to process restore file: " + ioe);
+                File savedStateName = new File(mStateDir, packageName);
+                newStateName.renameTo(savedStateName);
             } catch (Exception e) {
-                Log.e(TAG, "Final exception guard in restore:");
-                e.printStackTrace();
+                Log.e(TAG, "Error restoring data for " + packageName, e);
             }
         }
     }
@@ -1182,7 +1173,7 @@
             mContext.enforceCallingPermission("android.permission.BACKUP",
                     "endRestoreSession");
 
-            mRestoreTransport.endSession();
+            mRestoreTransport.finishRestore();
             mRestoreTransport = null;
             synchronized(BackupManagerService.this) {
                 if (BackupManagerService.this.mActiveRestoreSession == this) {
diff --git a/services/java/com/android/server/EntropyService.java b/services/java/com/android/server/EntropyService.java
index e51a0af..28f09f5 100644
--- a/services/java/com/android/server/EntropyService.java
+++ b/services/java/com/android/server/EntropyService.java
@@ -17,12 +17,16 @@
 package com.android.server;
 
 import java.io.File;
+import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
 
 import android.os.Binder;
 import android.os.Environment;
 import android.os.Handler;
 import android.os.Message;
+import android.os.SystemProperties;
 import android.util.Log;
 
 /**
@@ -49,6 +53,8 @@
     private static final int ENTROPY_WHAT = 1;
     private static final int ENTROPY_WRITE_PERIOD = 3 * 60 * 60 * 1000;  // 3 hrs
     private static final String RANDOM_DEV = "/dev/urandom";
+    private static final long START_TIME = System.currentTimeMillis();
+    private static final long START_NANOTIME = System.nanoTime();
 
     /**
      * Handler that periodically updates the entropy on disk.
@@ -67,6 +73,7 @@
 
     public EntropyService() {
         loadInitialEntropy();
+        addDeviceSpecificEntropy();
         writeEntropy();
         scheduleEntropyWriter();
     }
@@ -88,7 +95,47 @@
         try {
             RandomBlock.fromFile(RANDOM_DEV).toFile(ENTROPY_FILENAME);
         } catch (IOException e) {
-            Log.e(TAG, "unable to write entropy", e);
+            Log.w(TAG, "unable to write entropy", e);
+        }
+    }
+
+    /**
+     * Add additional information to the kernel entropy pool.  The
+     * information isn't necessarily "random", but that's ok.  Even
+     * sending non-random information to {@code /dev/urandom} is useful
+     * because, while it doesn't increase the "quality" of the entropy pool,
+     * it mixes more bits into the pool, which gives us a higher degree
+     * of uncertainty in the generated randomness.  Like nature, writes to
+     * the random device can only cause the quality of the entropy in the
+     * kernel to stay the same or increase.
+     *
+     * <p>For maximum effect, we try to target information which varies
+     * on a per-device basis, and is not easily observable to an
+     * attacker.
+     */
+    private void addDeviceSpecificEntropy() {
+        PrintWriter out = null;
+        try {
+            out = new PrintWriter(new FileOutputStream(RANDOM_DEV));
+            out.println("Copyright (C) 2009 The Android Open Source Project");
+            out.println("All Your Randomness Are Belong To Us");
+            out.println(START_TIME);
+            out.println(START_NANOTIME);
+            out.println(SystemProperties.get("ro.serialno"));
+            out.println(SystemProperties.get("ro.bootmode"));
+            out.println(SystemProperties.get("ro.baseband"));
+            out.println(SystemProperties.get("ro.carrier"));
+            out.println(SystemProperties.get("ro.bootloader"));
+            out.println(SystemProperties.get("ro.hardware"));
+            out.println(SystemProperties.get("ro.revision"));
+            out.println(System.currentTimeMillis());
+            out.println(System.nanoTime());
+        } catch (IOException e) {
+            Log.w(TAG, "Unable to add device specific data to the entropy pool", e);
+        } finally {
+            if (out != null) {
+                out.close();
+            }
         }
     }
 
diff --git a/services/java/com/android/server/PackageManagerBackupAgent.java b/services/java/com/android/server/PackageManagerBackupAgent.java
index cc84430..66fb86d 100644
--- a/services/java/com/android/server/PackageManagerBackupAgent.java
+++ b/services/java/com/android/server/PackageManagerBackupAgent.java
@@ -24,6 +24,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.Signature;
+import android.os.Build;
 import android.os.ParcelFileDescriptor;
 import android.util.Log;
 
@@ -52,7 +53,11 @@
     private static final String TAG = "PMBA";
     private static final boolean DEBUG = true;
 
-    private List<ApplicationInfo> mAllApps;
+    // key under which we store global metadata (individual app metadata
+    // is stored using the package name as a key)
+    private static final String GLOBAL_METADATA_KEY = "@meta@";
+
+    private List<PackageInfo> mAllPackages;
     private PackageManager mPackageManager;
     private HashMap<String, Metadata> mRestoredSignatures;
 
@@ -68,14 +73,15 @@
 
     // We're constructed with the set of applications that are participating
     // in backup.  This set changes as apps are installed & removed.
-    PackageManagerBackupAgent(PackageManager packageMgr, List<ApplicationInfo> apps) {
+    PackageManagerBackupAgent(PackageManager packageMgr, List<PackageInfo> packages) {
         mPackageManager = packageMgr;
-        mAllApps = apps;
+        mAllPackages = packages;
         mRestoredSignatures = null;
     }
 
     public Metadata getRestoredMetadata(String packageName) {
         if (mRestoredSignatures == null) {
+            Log.w(TAG, "getRestoredMetadata() before metadata read!");
             return null;
         }
 
@@ -86,111 +92,157 @@
     // the package name.
     public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
             ParcelFileDescriptor newState) {
-        HashSet<String> existing = parseStateFile(oldState);
-
-        // For each app we have on device, see if we've backed it up yet.  If not,
-        // write its signature block to the output, keyed on the package name.
         if (DEBUG) Log.v(TAG, "onBackup()");
+
         ByteArrayOutputStream bufStream = new ByteArrayOutputStream();  // we'll reuse these
         DataOutputStream outWriter = new DataOutputStream(bufStream);
-        for (ApplicationInfo app : mAllApps) {
-            String packName = app.packageName;
-            if (!existing.contains(packName)) {
-                // We haven't stored this app's signatures yet, so we do that now
-                try {
-                    PackageInfo info = mPackageManager.getPackageInfo(packName,
-                            PackageManager.GET_SIGNATURES);
-                    /*
-                     * Metadata for each package:
-                     *
-                     * int version       -- [4] the package's versionCode
-                     * byte[] signatures -- [len] flattened Signature[] of the package
-                     */
+        HashSet<String> existing = parseStateFile(oldState);
 
-                    // marshall the version code in a canonical form
-                    bufStream.reset();
-                    outWriter.writeInt(info.versionCode);
-                    byte[] versionBuf = bufStream.toByteArray();
+        try {
+            /*
+             * Global metadata:
+             *
+             * int version -- the SDK version of the OS itself on the device
+             *                that produced this backup set.  Used to reject
+             *                backups from later OSes onto earlier ones.
+             */
+            if (!existing.contains(GLOBAL_METADATA_KEY)) {
+                if (DEBUG) Log.v(TAG, "Storing global metadata key");
+                outWriter.writeInt(Build.VERSION.SDK_INT);
+                byte[] metadata = bufStream.toByteArray();
+                data.writeEntityHeader(GLOBAL_METADATA_KEY, metadata.length);
+                data.writeEntityData(metadata, metadata.length);
+            } else {
+                if (DEBUG) Log.v(TAG, "Global metadata key already stored");
+            }
 
-                    byte[] sigs = flattenSignatureArray(info.signatures);
+            // For each app we have on device, see if we've backed it up yet.  If not,
+            // write its signature block to the output, keyed on the package name.
+            for (PackageInfo pkg : mAllPackages) {
+                String packName = pkg.packageName;
+                if (!existing.contains(packName)) {
+                    // We haven't stored this app's signatures yet, so we do that now
+                    try {
+                        PackageInfo info = mPackageManager.getPackageInfo(packName,
+                                PackageManager.GET_SIGNATURES);
+                        /*
+                         * Metadata for each package:
+                         *
+                         * int version       -- [4] the package's versionCode
+                         * byte[] signatures -- [len] flattened Signature[] of the package
+                         */
 
-                    // !!! TODO: take out this debugging
-                    if (DEBUG) {
-                        Log.v(TAG, "+ metadata for " + packName + " version=" + info.versionCode);
+                        // marshall the version code in a canonical form
+                        bufStream.reset();
+                        outWriter.writeInt(info.versionCode);
+                        byte[] versionBuf = bufStream.toByteArray();
+
+                        byte[] sigs = flattenSignatureArray(info.signatures);
+
+                        // !!! TODO: take out this debugging
+                        if (DEBUG) {
+                            Log.v(TAG, "+ metadata for " + packName
+                                    + " version=" + info.versionCode
+                                    + " versionLen=" + versionBuf.length
+                                    + " sigsLen=" + sigs.length);
+                        }
+                        // Now we can write the backup entity for this package
+                        data.writeEntityHeader(packName, versionBuf.length + sigs.length);
+                        data.writeEntityData(versionBuf, versionBuf.length);
+                        data.writeEntityData(sigs, sigs.length);
+                    } catch (NameNotFoundException e) {
+                        // Weird; we just found it, and now are told it doesn't exist.
+                        // Treat it as having been removed from the device.
+                        existing.add(packName);
                     }
-                    // Now we can write the backup entity for this package
-                    data.writeEntityHeader(packName, versionBuf.length + sigs.length);
-                    data.writeEntityData(versionBuf, versionBuf.length);
-                    data.writeEntityData(sigs, sigs.length);
-                } catch (NameNotFoundException e) {
-                    // Weird; we just found it, and now are told it doesn't exist.
-                    // Treat it as having been removed from the device.
-                    existing.add(packName);
+                } else {
+                    // We've already backed up this app.  Remove it from the set so
+                    // we can tell at the end what has disappeared from the device.
+                    // !!! TODO: take out the debugging message
+                    if (DEBUG) Log.v(TAG, "= already backed up metadata for " + packName);
+                    if (!existing.remove(packName)) {
+                        Log.d(TAG, "*** failed to remove " + packName + " from package set!");
+                    }
+                }
+            }
+
+            // At this point, the only entries in 'existing' are apps that were
+            // mentioned in the saved state file, but appear to no longer be present
+            // on the device.  Write a deletion entity for them.
+            for (String app : existing) {
+                // !!! TODO: take out this msg
+                if (DEBUG) Log.v(TAG, "- removing metadata for deleted pkg " + app);
+                try {
+                    data.writeEntityHeader(app, -1);
                 } catch (IOException e) {
-                    // Real error writing data
-                    Log.e(TAG, "Unable to write package backup data file!");
+                    Log.e(TAG, "Unable to write package deletions!");
                     return;
                 }
-            } else {
-                // We've already backed up this app.  Remove it from the set so
-                // we can tell at the end what has disappeared from the device.
-                // !!! TODO: take out the debugging message
-                if (DEBUG) Log.v(TAG, "= already backed up metadata for " + packName);
-                if (!existing.remove(packName)) {
-                    Log.d(TAG, "*** failed to remove " + packName + " from package set!");
-                }
             }
-        }
-
-        // At this point, the only entries in 'existing' are apps that were
-        // mentioned in the saved state file, but appear to no longer be present
-        // on the device.  Write a deletion entity for them.
-        for (String app : existing) {
-            // !!! TODO: take out this msg
-            if (DEBUG) Log.v(TAG, "- removing metadata for deleted pkg " + app);
-            try {
-                data.writeEntityHeader(app, -1);
-            } catch (IOException e) {
-                Log.e(TAG, "Unable to write package deletions!");
-                return;
-            }
+        } catch (IOException e) {
+            // Real error writing data
+            Log.e(TAG, "Unable to write package backup data file!");
+            return;
         }
 
         // Finally, write the new state blob -- just the list of all apps we handled
-        writeStateFile(mAllApps, newState);
+        writeStateFile(mAllPackages, newState);
     }
 
     // "Restore" here is a misnomer.  What we're really doing is reading back the
     // set of app signatures associated with each backed-up app in this restore
     // image.  We'll use those later to determine what we can legitimately restore.
-    public void onRestore(BackupDataInput data, ParcelFileDescriptor newState)
+    public void onRestore(BackupDataInput data, int appVersionCode, ParcelFileDescriptor newState)
             throws IOException {
         List<ApplicationInfo> restoredApps = new ArrayList<ApplicationInfo>();
         HashMap<String, Metadata> sigMap = new HashMap<String, Metadata>();
+        if (DEBUG) Log.v(TAG, "onRestore()");
+        int storedSystemVersion = -1;
 
         while (data.readNextHeader()) {
+            String key = data.getKey();
             int dataSize = data.getDataSize();
-            byte[] buf = new byte[dataSize];
-            data.readEntityData(buf, 0, dataSize);
 
-            ByteArrayInputStream bufStream = new ByteArrayInputStream(buf);
-            DataInputStream in = new DataInputStream(bufStream);
-            int versionCode = in.readInt();
+            if (DEBUG) Log.v(TAG, "   got key=" + key + " dataSize=" + dataSize);
 
-            Signature[] sigs = unflattenSignatureArray(in);
-            String pkg = data.getKey();
-//          !!! TODO: take out this debugging
-            if (DEBUG) {
-                Log.i(TAG, "+ restored metadata for " + pkg
-                        + " versionCode=" + versionCode + " sigs=" + sigs);
+            // generic setup to parse any entity data
+            byte[] dataBuf = new byte[dataSize];
+            data.readEntityData(dataBuf, 0, dataSize);
+            ByteArrayInputStream baStream = new ByteArrayInputStream(dataBuf);
+            DataInputStream in = new DataInputStream(baStream);
+
+            if (key.equals(GLOBAL_METADATA_KEY)) {
+                storedSystemVersion = in.readInt();
+                if (DEBUG) Log.v(TAG, "   storedSystemVersion = " + storedSystemVersion);
+                if (storedSystemVersion > Build.VERSION.SDK_INT) {
+                    // returning before setting the sig map means we rejected the restore set
+                    Log.w(TAG, "Restore set was from a later version of Android; not restoring");
+                    return;
+                }
+                // !!! TODO: remove this debugging output
+                if (DEBUG) {
+                    Log.i(TAG, "Restore set version " + storedSystemVersion
+                            + " is compatible with OS version " + Build.VERSION.SDK_INT);
+                }
+            } else {
+                // it's a file metadata record
+                int versionCode = in.readInt();
+                Signature[] sigs = unflattenSignatureArray(in);
+//              !!! TODO: take out this debugging
+                if (DEBUG) {
+                    Log.i(TAG, "   restored metadata for " + key
+                            + " dataSize=" + dataSize
+                            + " versionCode=" + versionCode + " sigs=" + sigs);
+                }
+
+                ApplicationInfo app = new ApplicationInfo();
+                app.packageName = key;
+                restoredApps.add(app);
+                sigMap.put(key, new Metadata(versionCode, sigs));
             }
-
-            ApplicationInfo app = new ApplicationInfo();
-            app.packageName = pkg;
-            restoredApps.add(app);
-            sigMap.put(pkg, new Metadata(versionCode, sigs));
         }
 
+        // On successful completion, cache the signature map for the Backup Manager to use
         mRestoredSignatures = sigMap;
     }
 
@@ -225,6 +277,7 @@
 
         try {
             int num = in.readInt();
+            Log.v(TAG, " ... unflatten read " + num);
             sigs = new Signature[num];
             for (int i = 0; i < num; i++) {
                 int len = in.readInt();
@@ -273,20 +326,26 @@
         return set;
     }
 
-    // Util: write a set of names into a new state file
-    private void writeStateFile(List<ApplicationInfo> apps, ParcelFileDescriptor stateFile) {
+    // Util: write out our new backup state file
+    private void writeStateFile(List<PackageInfo> pkgs, ParcelFileDescriptor stateFile) {
         FileOutputStream outstream = new FileOutputStream(stateFile.getFileDescriptor());
         DataOutputStream out = new DataOutputStream(outstream);
 
-        for (ApplicationInfo app : apps) {
-            try {
-                byte[] pkgNameBuf = app.packageName.getBytes();
+        try {
+            // by the time we get here we know we've stored the global metadata record
+            byte[] metaNameBuf = GLOBAL_METADATA_KEY.getBytes();
+            out.writeInt(metaNameBuf.length);
+            out.write(metaNameBuf);
+
+            // now write all the app names too
+            for (PackageInfo pkg : pkgs) {
+                byte[] pkgNameBuf = pkg.packageName.getBytes();
                 out.writeInt(pkgNameBuf.length);
                 out.write(pkgNameBuf);
-            } catch (IOException e) {
-                Log.e(TAG, "Unable to write package manager state file!");
-                return;
             }
+        } catch (IOException e) {
+            Log.e(TAG, "Unable to write package manager state file!");
+            return;
         }
     }
 }
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 4b583e4..857bfaa 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -968,35 +968,7 @@
 
             if (Config.LOGV) Log.v(TAG, "getActivityInfo " + component + ": " + a);
             if (a != null && mSettings.isEnabledLP(a.info, flags)) {
-                ActivityInfo ainfo = PackageParser.generateActivityInfo(a, flags);
-                if (ainfo != null) {
-                    ApplicationInfo appInfo = getApplicationInfo(component.getPackageName(),
-                            PackageManager.GET_SUPPORTS_DENSITIES);
-                    if (appInfo != null &&
-                            (appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) == 0) {
-                        // Check if the screen size is same as what the application expect.
-                        CompatibilityInfo info = new CompatibilityInfo(appInfo);
-                        DisplayMetrics metrics = new DisplayMetrics();
-                        metrics.setTo(mMetrics);
-                        int orientation = mMetrics.widthPixels > mMetrics.heightPixels ?
-                                Configuration.ORIENTATION_LANDSCAPE :
-                                Configuration.ORIENTATION_PORTRAIT;
-                        metrics.updateMetrics(info, orientation);
-                        if (!info.mExpandable) {
-                            // Don't allow an app that cannot expand to handle rotation.
-                            ainfo.configChanges &= ~ ActivityInfo.CONFIG_ORIENTATION;
-                        } else {
-                            appInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
-                        }
-                        if (DEBUG_SETTINGS) {
-                            Log.d(TAG, "component=" + component +
-                                    ", expandable:" +
-                                    ((appInfo.flags &
-                                            ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0));
-                        }
-                    }
-                }
-                return ainfo;
+                return PackageParser.generateActivityInfo(a, flags);
             }
             if (mResolveComponentName.equals(component)) {
                 return mResolveActivity;
@@ -5937,7 +5909,7 @@
                     continue;
                 }
                 for (PackageSetting pkg:sus.packages) {
-                    if (pkg.grantedPermissions.contains (eachPerm)) {
+                    if (pkg.pkg.requestedPermissions.contains(eachPerm)) {
                         used = true;
                         break;
                     }
diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java
index b601ece..9f2856c 100644
--- a/services/java/com/android/server/TelephonyRegistry.java
+++ b/services/java/com/android/server/TelephonyRegistry.java
@@ -462,6 +462,15 @@
     //
 
     private void broadcastServiceStateChanged(ServiceState state) {
+        long ident = Binder.clearCallingIdentity();
+        try {
+            mBatteryStats.noteAirplaneMode(state.getState() == ServiceState.STATE_POWER_OFF);
+        } catch (RemoteException re) {
+            // Can't do much
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+
         Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
         Bundle data = new Bundle();
         state.fillInNotifierBundle(data);
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index ac176ca..5236a91 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -61,6 +61,7 @@
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.net.Uri;
+import android.os.BatteryStats;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Environment;
@@ -1523,7 +1524,9 @@
                 }
             }
             
-            synchronized(mBatteryStatsService.getActiveStatistics()) {
+            final BatteryStatsImpl bstats =
+                    (BatteryStatsImpl) mBatteryStatsService.getActiveStatistics();
+            synchronized(bstats) {
                 synchronized(mPidsSelfLocked) {
                     if (haveNewCpuStats) {
                         if (mBatteryStatsService.isOnBattery()) {
@@ -1535,12 +1538,18 @@
                                 if (pr != null) {
                                     BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
                                     ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
+                                } else {
+                                    BatteryStatsImpl.Uid.Proc ps =
+                                            bstats.getProcessStatsLocked(st.name);
+                                    if (ps != null) {
+                                        ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
+                                    }
                                 }
                             }
                         }
                     }
                 }
-        
+
                 if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
                     mLastWriteTime = now;
                     mBatteryStatsService.getActiveStatistics().writeLocked();
@@ -4875,9 +4884,11 @@
                 isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
                         || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
             }
-            ensurePackageDexOpt(app.info.packageName);
-            if (app.instrumentationInfo != null) {
-                ensurePackageDexOpt(app.instrumentationInfo.packageName);
+            ensurePackageDexOpt(app.instrumentationInfo != null
+                    ? app.instrumentationInfo.packageName
+                    : app.info.packageName);
+            if (app.instrumentationClass != null) {
+                ensurePackageDexOpt(app.instrumentationClass.getPackageName());
             }
             thread.bindApplication(processName, app.instrumentationInfo != null
                     ? app.instrumentationInfo : app.info, providers,
@@ -8333,6 +8344,7 @@
                 report.crashInfo.throwFileName = trace.getFileName();
                 report.crashInfo.throwClassName = trace.getClassName();
                 report.crashInfo.throwMethodName = trace.getMethodName();
+                report.crashInfo.throwLineNumber = trace.getLineNumber();
             } else if (r.notResponding) {
                 report.type = ApplicationErrorReport.TYPE_ANR;
                 report.anrInfo = new ApplicationErrorReport.AnrInfo();
@@ -12631,51 +12643,63 @@
     }
 
     public boolean profileControl(String process, boolean start,
-            String path) throws RemoteException {
+            String path, ParcelFileDescriptor fd) throws RemoteException {
 
-        synchronized (this) {
-            // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
-            // its own permission.
-            if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
-                    != PackageManager.PERMISSION_GRANTED) {
-                throw new SecurityException("Requires permission "
-                        + android.Manifest.permission.SET_ACTIVITY_WATCHER);
-            }
-            
-            ProcessRecord proc = null;
-            try {
-                int pid = Integer.parseInt(process);
-                synchronized (mPidsSelfLocked) {
-                    proc = mPidsSelfLocked.get(pid);
+        try {
+            synchronized (this) {
+                // note: hijacking SET_ACTIVITY_WATCHER, but should be changed to
+                // its own permission.
+                if (checkCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER)
+                        != PackageManager.PERMISSION_GRANTED) {
+                    throw new SecurityException("Requires permission "
+                            + android.Manifest.permission.SET_ACTIVITY_WATCHER);
                 }
-            } catch (NumberFormatException e) {
-            }
-            
-            if (proc == null) {
-                HashMap<String, SparseArray<ProcessRecord>> all
-                        = mProcessNames.getMap();
-                SparseArray<ProcessRecord> procs = all.get(process);
-                if (procs != null && procs.size() > 0) {
-                    proc = procs.valueAt(0);
+                
+                if (start && fd == null) {
+                    throw new IllegalArgumentException("null fd");
                 }
-            }
-            
-            if (proc == null || proc.thread == null) {
-                throw new IllegalArgumentException("Unknown process: " + process);
-            }
-            
-            boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
-            if (isSecure) {
-                if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
-                    throw new SecurityException("Process not debuggable: " + proc);
+                
+                ProcessRecord proc = null;
+                try {
+                    int pid = Integer.parseInt(process);
+                    synchronized (mPidsSelfLocked) {
+                        proc = mPidsSelfLocked.get(pid);
+                    }
+                } catch (NumberFormatException e) {
                 }
-            }
+                
+                if (proc == null) {
+                    HashMap<String, SparseArray<ProcessRecord>> all
+                            = mProcessNames.getMap();
+                    SparseArray<ProcessRecord> procs = all.get(process);
+                    if (procs != null && procs.size() > 0) {
+                        proc = procs.valueAt(0);
+                    }
+                }
+                
+                if (proc == null || proc.thread == null) {
+                    throw new IllegalArgumentException("Unknown process: " + process);
+                }
+                
+                boolean isSecure = "1".equals(SystemProperties.get(SYSTEM_SECURE, "0"));
+                if (isSecure) {
+                    if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
+                        throw new SecurityException("Process not debuggable: " + proc);
+                    }
+                }
             
-            try {
-                proc.thread.profilerControl(start, path);
+                proc.thread.profilerControl(start, path, fd);
+                fd = null;
                 return true;
-            } catch (RemoteException e) {
-                throw new IllegalStateException("Process disappeared");
+            }
+        } catch (RemoteException e) {
+            throw new IllegalStateException("Process disappeared");
+        } finally {
+            if (fd != null) {
+                try {
+                    fd.close();
+                } catch (IOException e) {
+                }
             }
         }
     }
diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java
index 9a4b642..39a1ee0 100644
--- a/services/java/com/android/server/am/BatteryStatsService.java
+++ b/services/java/com/android/server/am/BatteryStatsService.java
@@ -16,9 +16,6 @@
 
 package com.android.server.am;
 
-import com.android.internal.app.IBatteryStats;
-import com.android.internal.os.BatteryStatsImpl;
-
 import android.content.Context;
 import android.os.Binder;
 import android.os.IBinder;
@@ -26,8 +23,12 @@
 import android.os.Process;
 import android.os.ServiceManager;
 import android.telephony.SignalStrength;
+import android.telephony.TelephonyManager;
 import android.util.Log;
 
+import com.android.internal.app.IBatteryStats;
+import com.android.internal.os.BatteryStatsImpl;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
@@ -191,7 +192,14 @@
             mStats.notePhoneDataConnectionStateLocked(dataType, hasData);
         }
     }
-    
+
+    public void noteAirplaneMode(boolean airplaneMode) {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteAirplaneModeLocked(airplaneMode);
+        }
+    }
+
     public void noteWifiOn(int uid) {
         enforceCallingPermission();
         synchronized (mStats) {
diff --git a/telephony/java/com/android/internal/telephony/RIL.java b/telephony/java/com/android/internal/telephony/RIL.java
index c6b7601..9f780c9 100644
--- a/telephony/java/com/android/internal/telephony/RIL.java
+++ b/telephony/java/com/android/internal/telephony/RIL.java
@@ -2067,13 +2067,13 @@
  | sed -re 's/\{([^,]+),[^,]+,([^}]+).+/case \1: ret = \2(p); break;/'
              */
             case RIL_REQUEST_GET_SIM_STATUS: ret =  responseIccCardStatus(p); break;
-            case RIL_REQUEST_ENTER_SIM_PIN: ret =  responseVoid(p); break;
-            case RIL_REQUEST_ENTER_SIM_PUK: ret =  responseVoid(p); break;
-            case RIL_REQUEST_ENTER_SIM_PIN2: ret =  responseVoid(p); break;
-            case RIL_REQUEST_ENTER_SIM_PUK2: ret =  responseVoid(p); break;
-            case RIL_REQUEST_CHANGE_SIM_PIN: ret =  responseVoid(p); break;
-            case RIL_REQUEST_CHANGE_SIM_PIN2: ret =  responseVoid(p); break;
-            case RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION: ret =  responseVoid(p); break;
+            case RIL_REQUEST_ENTER_SIM_PIN: ret =  responseInts(p); break;
+            case RIL_REQUEST_ENTER_SIM_PUK: ret =  responseInts(p); break;
+            case RIL_REQUEST_ENTER_SIM_PIN2: ret =  responseInts(p); break;
+            case RIL_REQUEST_ENTER_SIM_PUK2: ret =  responseInts(p); break;
+            case RIL_REQUEST_CHANGE_SIM_PIN: ret =  responseInts(p); break;
+            case RIL_REQUEST_CHANGE_SIM_PIN2: ret =  responseInts(p); break;
+            case RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION: ret =  responseInts(p); break;
             case RIL_REQUEST_GET_CURRENT_CALLS: ret =  responseCallList(p); break;
             case RIL_REQUEST_DIAL: ret =  responseVoid(p); break;
             case RIL_REQUEST_GET_IMSI: ret =  responseString(p); break;
@@ -2108,7 +2108,7 @@
             case RIL_REQUEST_ANSWER: ret =  responseVoid(p); break;
             case RIL_REQUEST_DEACTIVATE_DATA_CALL: ret =  responseVoid(p); break;
             case RIL_REQUEST_QUERY_FACILITY_LOCK: ret =  responseInts(p); break;
-            case RIL_REQUEST_SET_FACILITY_LOCK: ret =  responseVoid(p); break;
+            case RIL_REQUEST_SET_FACILITY_LOCK: ret =  responseInts(p); break;
             case RIL_REQUEST_CHANGE_BARRING_PASSWORD: ret =  responseVoid(p); break;
             case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE: ret =  responseInts(p); break;
             case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC: ret =  responseVoid(p); break;
diff --git a/telephony/java/com/android/internal/telephony/cdma/SignalToneUtil.java b/telephony/java/com/android/internal/telephony/cdma/SignalToneUtil.java
index 925a755..44958e9 100644
--- a/telephony/java/com/android/internal/telephony/cdma/SignalToneUtil.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SignalToneUtil.java
@@ -22,6 +22,9 @@
 import android.media.ToneGenerator;
 
 public class SignalToneUtil {
+    /** A marker that isn't a valid TONE */
+    public static final int CDMA_INVALID_TONE = -1;
+
     // public final int int IS95_CONST_IR_SIGNAL_TYPE_TYPE;
     static public final int IS95_CONST_IR_SIGNAL_TONE = 0;
     static public final int IS95_CONST_IR_SIGNAL_ISDN = 1;
@@ -76,7 +79,7 @@
     private static Integer signalParamHash(int signalType, int alertPitch, int signal) {
         if ((signalType < 0) || (signalType > 256) || (alertPitch > 256) ||
                 (alertPitch < 0) || (signal > 256) || (signal < 0)) {
-            return new Integer(ToneGenerator.TONE_CDMA_INVALID);
+            return new Integer(CDMA_INVALID_TONE);
         }
         return new Integer(signalType * 256 * 256 + alertPitch * 256 + signal);
     }
@@ -84,7 +87,7 @@
     public static int getAudioToneFromSignalInfo(int signalType, int alertPitch, int signal) {
         Integer result = hm.get(signalParamHash(signalType, alertPitch, signal));
         if (result == null) {
-            return ToneGenerator.TONE_CDMA_INVALID;
+            return CDMA_INVALID_TONE;
         }
         return result;
     }
@@ -100,13 +103,13 @@
                         ToneGenerator.TONE_CDMA_CALL_SIGNAL_ISDN_INTERGROUP);
 
         hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_ISDN, TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN,
-                IS95_CONST_IR_SIG_ISDN_SP_PRI), ToneGenerator.TONE_CDMA_CALL_SIGNAL_SP_PRI);
+                IS95_CONST_IR_SIG_ISDN_SP_PRI), ToneGenerator.TONE_CDMA_CALL_SIGNAL_ISDN_SP_PRI);
 
         hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_ISDN, TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN,
                 IS95_CONST_IR_SIG_ISDN_PAT_3), ToneGenerator.TONE_CDMA_CALL_SIGNAL_ISDN_PAT3);
 
         hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_ISDN, TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN,
-                IS95_CONST_IR_SIG_ISDN_PING), ToneGenerator.TONE_CDMA_CALL_SIGNAL_ISDN_RING_RING);
+                IS95_CONST_IR_SIG_ISDN_PING), ToneGenerator.TONE_CDMA_CALL_SIGNAL_ISDN_PING_RING);
 
         hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_ISDN, TAPIAMSSCDMA_SIGNAL_PITCH_UNKNOWN,
                 IS95_CONST_IR_SIG_ISDN_PAT_5), ToneGenerator.TONE_CDMA_CALL_SIGNAL_ISDN_PAT5);
@@ -163,7 +166,7 @@
                 IS95_CONST_IR_SIG_IS54B_L), ToneGenerator.TONE_CDMA_HIGH_L);
 
         hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_MED,
-                IS95_CONST_IR_SIG_IS54B_L), ToneGenerator.TONE_CDMA_INVALID);
+                IS95_CONST_IR_SIG_IS54B_L), ToneGenerator.TONE_CDMA_MED_L);
 
         hm.put(signalParamHash(IS95_CONST_IR_SIGNAL_IS54B, IS95_CONST_IR_ALERT_LOW,
                 IS95_CONST_IR_SIG_IS54B_L), ToneGenerator.TONE_CDMA_LOW_L);
diff --git a/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java b/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java
index 278beef..55e5adc 100644
--- a/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java
+++ b/telephony/java/com/android/internal/telephony/gsm/PdpConnection.java
@@ -58,18 +58,9 @@
     private String pdp_name;
     private ApnSetting apn;
 
-    // dataLink is only used to support pppd link
-    private DataLink dataLink;
-
     //***** Constructor
     PdpConnection(GSMPhone phone) {
         super(phone);
-        this.dataLink = null;
-
-        if (SystemProperties.get("ro.radio.use-ppp","no").equals("yes")) {
-            dataLink = new PppLink((GsmDataConnectionTracker) phone.mDataConnection, phone);
-            dataLink.setOnLinkChange(this, EVENT_LINK_STATE_CHANGED, null);
-        }
     }
 
     /**
@@ -97,10 +88,6 @@
     }
 
     private void tearDownData(Message msg) {
-        if (dataLink != null) {
-            dataLink.disconnect();
-        }
-
         if (phone.mCM.getRadioState().isOn()) {
             phone.mCM.deactivateDataCall(cid, obtainMessage(EVENT_DEACTIVATE_DONE, msg));
         }
@@ -313,11 +300,7 @@
                     }
                 }
 
-                if (dataLink != null) {
-                    dataLink.connect();
-                } else {
-                    onLinkStateChanged(DataLink.LinkState.LINK_UP);
-                }
+                onLinkStateChanged(DataLink.LinkState.LINK_UP);
 
                 if (DBG) log("PDP setup on cid = " + cid);
             }
diff --git a/telephony/java/com/android/internal/telephony/gsm/PppLink.java b/telephony/java/com/android/internal/telephony/gsm/PppLink.java
deleted file mode 100644
index 9627696..0000000
--- a/telephony/java/com/android/internal/telephony/gsm/PppLink.java
+++ /dev/null
@@ -1,219 +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.database.Cursor;
-import android.os.Message;
-import android.os.SystemProperties;
-import android.os.SystemService;
-import android.util.Log;
-
-import com.android.internal.telephony.DataLink;
-import com.android.internal.telephony.DataConnectionTracker.State;
-import com.android.internal.telephony.PhoneBase;
-import com.android.internal.util.ArrayUtils;
-
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-
-/**
- * Represents a PPP link.
- *
- * Ideally this would be managed by the RIL implementation, but
- * we currently have implementations where this is not the case.
- *
- * {@hide}
- */
-final class PppLink extends DataLink {
-    private static final String LOG_TAG = "GSM";
-
-    static final String PATH_PPP_OPERSTATE = "/sys/class/net/ppp0/operstate";
-    static final String SERVICE_PPPD_GPRS = "pppd_gprs";
-    static final String PROPERTY_PPPD_EXIT_CODE = "net.gprs.ppp-exit";
-    static final int POLL_SYSFS_MILLIS = 5 * 1000;
-    static final int EVENT_POLL_DATA_CONNECTION = 2;
-    static final int EVENT_PPP_OPERSTATE_CHANGED = 8;
-    static final int EVENT_PPP_PIDFILE_CHANGED = 9;
-
-    static final byte[] UP_ASCII_STRING = new byte[] {
-        'u' & 0xff,
-        'p' & 0xff,
-    };
-    static final byte[] DOWN_ASCII_STRING = new byte[] {
-        'd' & 0xff,
-        'o' & 0xff,
-        'w' & 0xff,
-        'n' & 0xff,
-    };
-    static final byte[] UNKNOWN_ASCII_STRING = new byte[] {
-        'u' & 0xff,
-        'n' & 0xff,
-        'k' & 0xff,
-        'n' & 0xff,
-        'o' & 0xff,
-        'w' & 0xff,
-        'n' & 0xff,
-    };
-    private final byte[] mCheckPPPBuffer = new byte[32];
-
-    private PhoneBase phone;
-
-    int lastPppdExitCode = EXIT_OK;
-
-
-    PppLink(GsmDataConnectionTracker dc, GSMPhone p) {
-        super(dc);
-        this.phone = p;
-    }
-
-    public void connect() {
-        // Clear any previous exit code
-        SystemProperties.set(PROPERTY_PPPD_EXIT_CODE, "");
-        SystemService.start(SERVICE_PPPD_GPRS);
-        removeMessages(EVENT_POLL_DATA_CONNECTION);
-        Message poll = obtainMessage();
-        poll.what = EVENT_POLL_DATA_CONNECTION;
-        sendMessageDelayed(poll, POLL_SYSFS_MILLIS);
-    }
-
-    public void disconnect() {
-        SystemService.stop(SERVICE_PPPD_GPRS);
-    }
-
-    public int getLastLinkExitCode() {
-        return lastPppdExitCode;
-    }
-
-    public void setPasswordInfo(Cursor cursor) {
-        StringBuilder builder = new StringBuilder();
-        FileOutputStream output = null;
-
-        try {
-            output = new FileOutputStream("/etc/ppp/pap-secrets");
-            if (cursor.moveToFirst()) {
-                do {
-                    builder.append(cursor.getString(cursor.getColumnIndex("user")));
-                    builder.append(" ");
-                    builder.append(cursor.getString(cursor.getColumnIndex("server")));
-                    builder.append(" ");
-                    builder.append(cursor.getString(cursor.getColumnIndex("password")));
-                    builder.append("\n");
-                } while (cursor.moveToNext());
-            }
-
-            output.write(builder.toString().getBytes());
-        } catch (java.io.IOException e) {
-            Log.e(LOG_TAG, "Could not create '/etc/ppp/pap-secrets'", e);
-        } finally {
-            try {
-                if (output != null) output.close();
-            } catch (java.io.IOException e) {
-                Log.e(LOG_TAG, "Error closing '/etc/ppp/pap-secrets'", e);
-            }
-        }
-    }
-
-    public void handleMessage (Message msg) {
-
-        switch (msg.what) {
-
-            case EVENT_POLL_DATA_CONNECTION:
-                checkPPP();
-
-                // keep polling in case interface goes down
-                if (dataConnection.getState() != State.IDLE) {
-                    Message poll = obtainMessage();
-                    poll.what = EVENT_POLL_DATA_CONNECTION;
-                    sendMessageDelayed(poll, POLL_SYSFS_MILLIS);
-                }
-                break;
-        }
-    }
-
-    private void checkPPP() {
-        boolean connecting = (dataConnection.getState() == State.CONNECTING);
-
-        try {
-            RandomAccessFile file = new RandomAccessFile(PATH_PPP_OPERSTATE, "r");
-            file.read(mCheckPPPBuffer);
-            file.close();
-
-            // Unfortunately, we're currently seeing operstate
-            // "unknown" where one might otherwise expect "up"
-            if (ArrayUtils.equals(mCheckPPPBuffer, UP_ASCII_STRING, UP_ASCII_STRING.length)
-                    || ArrayUtils.equals(mCheckPPPBuffer, UNKNOWN_ASCII_STRING,
-                    UNKNOWN_ASCII_STRING.length)
-                    && dataConnection.getState() == State.CONNECTING) {
-
-                Log.i(LOG_TAG,
-                "found ppp interface. Notifying GPRS connected");
-
-                if (mLinkChangeRegistrant != null) {
-                    mLinkChangeRegistrant.notifyResult(LinkState.LINK_UP);
-                }
-
-                connecting = false;
-            } else if (dataConnection.getState() == State.CONNECTED
-                    && ArrayUtils.equals(mCheckPPPBuffer, DOWN_ASCII_STRING,
-                    DOWN_ASCII_STRING.length)) {
-
-                Log.i(LOG_TAG,
-                "ppp interface went down. Reconnecting...");
-
-                if (mLinkChangeRegistrant != null) {
-                    mLinkChangeRegistrant.notifyResult(LinkState.LINK_DOWN);
-                }
-            }
-        } catch (IOException ex) {
-            if (! (ex instanceof FileNotFoundException)) {
-                Log.i(LOG_TAG, "Poll ppp0 ex " + ex.toString());
-            }
-
-            if (dataConnection.getState() == State.CONNECTED &&
-                    mLinkChangeRegistrant != null) {
-                mLinkChangeRegistrant.notifyResult(LinkState.LINK_DOWN);
-            }
-        }
-
-        // CONNECTING means pppd has started but negotiation is not complete
-        // If we're still CONNECTING here, check to see if pppd has
-        // already exited
-        if (connecting) {
-            String exitCode;
-
-            exitCode = SystemProperties.get(PROPERTY_PPPD_EXIT_CODE, "");
-
-            if (!exitCode.equals("")) {
-                // pppd has exited. Let's figure out why
-                lastPppdExitCode = Integer.parseInt(exitCode);
-
-                Log.d(LOG_TAG,"pppd exited with " + exitCode);
-
-                if (mLinkChangeRegistrant != null) {
-                    mLinkChangeRegistrant.notifyResult(LinkState.LINK_EXITED);
-                }
-            }
-        }
-
-    }
-
-    protected void log(String s) {
-        Log.d(LOG_TAG, "[PppLink] " + s);
-    }
-}
diff --git a/test-runner/android/test/SyncBaseInstrumentation.java b/test-runner/android/test/SyncBaseInstrumentation.java
index bf9e783..a860bb3 100644
--- a/test-runner/android/test/SyncBaseInstrumentation.java
+++ b/test-runner/android/test/SyncBaseInstrumentation.java
@@ -19,7 +19,6 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.os.Bundle;
-import android.os.RemoteException;
 import android.os.SystemClock;
 import android.net.Uri;
 import android.accounts.Account;
@@ -45,13 +44,12 @@
      * Syncs the specified provider.
      * @throws Exception
      */
-    protected void syncProvider(Uri uri, String account, String authority) throws Exception {
+    protected void syncProvider(Uri uri, String accountName, String authority) throws Exception {
         Bundle extras = new Bundle();
-        extras.putBoolean(ContentResolver.SYNC_EXTRAS_FORCE, true);
-        Account account1 = new Account(account, "com.google.GAIA");
-        extras.putParcelable(ContentResolver.SYNC_EXTRAS_ACCOUNT, account1);
+        extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
+        Account account = new Account(accountName, "com.google.GAIA");
 
-        mContentResolver.startSync(uri, extras);
+        ContentResolver.requestSync(account, authority, extras);
         long startTimeInMillis = SystemClock.elapsedRealtime();
         long endTimeInMillis = startTimeInMillis + MAX_TIME_FOR_SYNC_IN_MINS * 60000;
 
@@ -66,7 +64,7 @@
                 break;
             }
 
-            if (isSyncActive(account1, authority)) {
+            if (ContentResolver.isSyncActive(account, authority)) {
                 counter = 0;
                 continue;
             }
@@ -75,24 +73,7 @@
     }
 
     protected void cancelSyncsandDisableAutoSync() {
-        try {
-            ContentResolver.getContentService().setListenForNetworkTickles(false);
-        } catch (RemoteException e) {
-        }
-        mContentResolver.cancelSync(null);
-    }
-
-    /**
-     * This method tests if any sync is active or not. Sync is considered to be active if the
-     * entry is in either the Pending or Active tables.
-     * @return
-     */
-    private boolean isSyncActive(Account account, String authority) {
-        try {
-            return ContentResolver.getContentService().isSyncActive(account,
-                    authority);
-        } catch (RemoteException e) {
-            return false;
-        }
+        ContentResolver.setMasterSyncAutomatically(false);
+        ContentResolver.cancelSync(null /* all accounts */, null /* all authorities */);
     }
 }
diff --git a/tests/AndroidTests/src/com/android/unit_tests/SearchManagerTest.java b/tests/AndroidTests/src/com/android/unit_tests/SearchManagerTest.java
index f03a779..c4f1ab6 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/SearchManagerTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/SearchManagerTest.java
@@ -126,26 +126,6 @@
     }
     
     /**
-     * The goal of this test is to confirm that we can *only* obtain a search manager
-     * interface from an Activity context.
-     */
-    @MediumTest
-    public void testSearchManagerContextRestrictions() {
-        SearchManager searchManager1 = (SearchManager)
-                mContext.getSystemService(Context.SEARCH_SERVICE);
-        assertNotNull(searchManager1);
-        
-        Context applicationContext = mContext.getApplicationContext();
-        // this should fail, because you can't get a SearchManager from a non-Activity context
-        try {
-            applicationContext.getSystemService(Context.SEARCH_SERVICE);
-            assertFalse("Shouldn't retrieve SearchManager from a non-Activity context", true);
-        } catch (AndroidRuntimeException e) {
-            // happy here - we should catch this.
-        }
-    }
-    
-    /**
      * The goal of this test is to confirm that we can obtain
      * a search manager at any time, and that for any given context,
      * it is a singleton.
@@ -163,17 +143,19 @@
 
     @MediumTest
     public void testSearchables() {
+        SearchManager searchManager = (SearchManager)
+                mContext.getSystemService(Context.SEARCH_SERVICE);
         SearchableInfo si;
 
-        si = SearchManager.getSearchableInfo(SEARCHABLE_ACTIVITY, false);
+        si = searchManager.getSearchableInfo(SEARCHABLE_ACTIVITY, false);
         assertNotNull(si);
-        assertFalse(SearchManager.isDefaultSearchable(si));
-        si = SearchManager.getSearchableInfo(SEARCHABLE_ACTIVITY, true);
+        assertFalse(searchManager.isDefaultSearchable(si));
+        si = searchManager.getSearchableInfo(SEARCHABLE_ACTIVITY, true);
         assertNotNull(si);
-        assertTrue(SearchManager.isDefaultSearchable(si));
-        si = SearchManager.getSearchableInfo(null, true);
+        assertTrue(searchManager.isDefaultSearchable(si));
+        si = searchManager.getSearchableInfo(null, true);
         assertNotNull(si);
-        assertTrue(SearchManager.isDefaultSearchable(si));
+        assertTrue(searchManager.isDefaultSearchable(si));
     }
 
     /**
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java b/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java
index a389461..39ce1f2 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java
@@ -18,6 +18,7 @@
 
 import android.os.Handler;
 import android.os.Message;
+import android.webkit.WebStorage;
 
 import java.util.HashMap;
 
@@ -25,7 +26,7 @@
     
     private EventSender mEventSender;
     private LayoutTestController mLayoutTestController;
-    
+
     private static final int EVENT_DOM_LOG = 1;
     private static final int EVENT_FIRE_KBD = 2;
     private static final int EVENT_KEY_DOWN_1 = 3;
@@ -57,6 +58,8 @@
     private static final int LAYOUT_SET_WINDOW_KEY = 38;
     private static final int LAYOUT_TEST_REPAINT = 39;
     private static final int LAYOUT_WAIT_UNTIL_DONE = 40;
+    private static final int LAYOUT_DUMP_DATABASE_CALLBACKS = 41;
+    private static final int LAYOUT_SET_CAN_OPEN_WINDOWS = 42;
     
     CallbackProxy(EventSender eventSender, 
             LayoutTestController layoutTestController) {
@@ -190,6 +193,14 @@
         case LAYOUT_WAIT_UNTIL_DONE:
             mLayoutTestController.waitUntilDone();
             break;
+
+        case LAYOUT_DUMP_DATABASE_CALLBACKS:
+            mLayoutTestController.dumpDatabaseCallbacks();
+            break;
+
+        case LAYOUT_SET_CAN_OPEN_WINDOWS:
+            mLayoutTestController.setCanOpenWindows();
+            break;
         }
     }
 
@@ -325,4 +336,20 @@
         obtainMessage(LAYOUT_WAIT_UNTIL_DONE).sendToTarget();
     }
 
+    public void dumpDatabaseCallbacks() {
+        obtainMessage(LAYOUT_DUMP_DATABASE_CALLBACKS).sendToTarget();
+    }
+
+    public void clearAllDatabases() {
+        WebStorage.getInstance().deleteAllDatabases();
+    }
+
+    public void setDatabaseQuota(long quota) {
+        WebStorage.getInstance().setQuotaForOrigin("file://", quota);
+    }
+
+    public void setCanOpenWindows() {
+        obtainMessage(LAYOUT_SET_CAN_OPEN_WINDOWS).sendToTarget();
+    }
+
 }
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
index 95a7ae3..ede5197 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
@@ -87,7 +87,15 @@
         "fast/regex/test1.html",
         "fast/regex/slow.html",
         // RegExp is too large, causing OOM
-        "fast/js/regexp-charclass-crash.html"
+        "fast/js/regexp-charclass-crash.html",
+        // The Android browser has no notion of private browsing.
+        "storage/private-browsing-readonly.html",
+        "storage/domstorage/localstorage/private-browsing-affects-storage.html",
+        "storage/domstorage/sessionstorage/private-browsing-affects-storage.html",
+        // Android layout tests are stored in "layout_tests". The following two
+        // tests expect "LayoutTests" in their output.
+        "storage/domstorage/localstorage/iframe-events.html",
+        "storage/domstorage/sessionstorage/iframe-events.html"
     };
     
     static void fillIgnoreResultSet() {
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestController.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestController.java
index 6166dd0..e1d802a 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestController.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestController.java
@@ -58,5 +58,8 @@
     public void queueLoad(String Url, String frameTarget);
 
     public void setAcceptsEditing(boolean b);
-	
+
+    // For storage tests
+    public void dumpDatabaseCallbacks();
+    public void setCanOpenWindows();
 }
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
index 1ba291c..02658a1 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
@@ -31,6 +31,7 @@
 import android.webkit.SslErrorHandler;
 import android.webkit.WebChromeClient;
 import android.webkit.WebSettings;
+import android.webkit.WebStorage;
 import android.webkit.WebView;
 import android.webkit.WebViewClient;
 import android.widget.LinearLayout;
@@ -38,6 +39,8 @@
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
 import java.util.Vector;
 
 public class TestShellActivity extends Activity implements LayoutTestController {
@@ -90,52 +93,13 @@
         setContentView(contentView);
 
         mWebView = new WebView(this);
-        mWebView.getSettings().setJavaScriptEnabled(true);
-        mWebView.setWebChromeClient(mChromeClient);
-        mWebView.setWebViewClient(new WebViewClient(){
-
-            @Override
-            public void onPageFinished(WebView view, String url) {
-                Log.v(LOGTAG, "onPageFinished, url=" + url);
-                super.onPageFinished(view, url);
-            }
-
-            @Override
-            public void onPageStarted(WebView view, String url, Bitmap favicon) {
-                Log.v(LOGTAG, "onPageStarted, url=" + url);
-                super.onPageStarted(view, url, favicon);
-            }
-
-            @Override
-            public void onReceivedError(WebView view, int errorCode, String description,
-                    String failingUrl) {
-                Log.v(LOGTAG, "onReceivedError, errorCode=" + errorCode
-                        + ", desc=" + description + ", url=" + failingUrl);
-                super.onReceivedError(view, errorCode, description, failingUrl);
-            }
-
-            @Override
-            public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler,
-                    String host, String realm) {
-                handler.cancel();
-            }
-
-            @Override
-            public void onReceivedSslError(WebView view, SslErrorHandler handler,
-                    SslError error) {
-                handler.proceed();
-            }
-
-        });
         mEventSender = new WebViewEventSender(mWebView);
         mCallbackProxy = new CallbackProxy(mEventSender, this);
 
-        mWebView.addJavascriptInterface(mCallbackProxy, "layoutTestController");
-        mWebView.addJavascriptInterface(mCallbackProxy, "eventSender");
+        setupWebViewForLayoutTests(mWebView, mCallbackProxy);
+
         contentView.addView(mWebView, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT, 0.0f));
  
-        mWebView.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL);
-            
         mHandler = new AsyncHandler();
         
         Intent intent = getIntent();
@@ -217,6 +181,12 @@
             if (mDialogStrings != null)
                 os.write(mDialogStrings.toString().getBytes());
             mDialogStrings = null;
+            if (mDatabaseCallbackStrings != null)
+                os.write(mDatabaseCallbackStrings.toString().getBytes());
+            mDatabaseCallbackStrings = null;
+            if (mConsoleMessages != null)
+                os.write(mConsoleMessages.toString().getBytes());
+            mConsoleMessages = null;
             if (webkitData != null)
                 os.write(webkitData.getBytes());
             os.flush();
@@ -359,7 +329,52 @@
     public void testRepaint() {
         mWebView.invalidate();
     }
-    
+
+    public void dumpDatabaseCallbacks() {
+        Log.v(LOGTAG, "dumpDatabaseCallbacks called.");
+        mDumpDatabaseCallbacks = true;
+    }
+
+    public void setCanOpenWindows() {
+        Log.v(LOGTAG, "setCanOpenWindows called.");
+        mCanOpenWindows = true;
+    }
+
+    private final WebViewClient mViewClient = new WebViewClient(){
+        @Override
+        public void onPageFinished(WebView view, String url) {
+            Log.v(LOGTAG, "onPageFinished, url=" + url);
+            super.onPageFinished(view, url);
+        }
+
+        @Override
+        public void onPageStarted(WebView view, String url, Bitmap favicon) {
+            Log.v(LOGTAG, "onPageStarted, url=" + url);
+            super.onPageStarted(view, url, favicon);
+        }
+
+        @Override
+        public void onReceivedError(WebView view, int errorCode, String description,
+                String failingUrl) {
+            Log.v(LOGTAG, "onReceivedError, errorCode=" + errorCode
+                    + ", desc=" + description + ", url=" + failingUrl);
+            super.onReceivedError(view, errorCode, description, failingUrl);
+        }
+
+        @Override
+        public void onReceivedHttpAuthRequest(WebView view, HttpAuthHandler handler,
+                String host, String realm) {
+            handler.cancel();
+        }
+
+        @Override
+        public void onReceivedSslError(WebView view, SslErrorHandler handler,
+                SslError error) {
+            handler.proceed();
+        }
+    };
+
+
     private final WebChromeClient mChromeClient = new WebChromeClient() {
         @Override
         public void onProgressChanged(WebView view, int newProgress) {
@@ -434,6 +449,72 @@
             result.confirm();
             return true;
         }
+
+        @Override
+        public void onExceededDatabaseQuota(String url_str,
+                String databaseIdentifier, long currentQuota,
+                WebStorage.QuotaUpdater callback) {
+            if (mDumpDatabaseCallbacks) {
+                if (mDatabaseCallbackStrings == null) {
+                    mDatabaseCallbackStrings = new StringBuffer();
+                }
+
+                String protocol = "";
+                String host = "";
+                int port = 0;
+
+                try {
+                    URL url = new URL(url_str);
+                    protocol = url.getProtocol();
+                    host = url.getHost();
+                    if (url.getPort() > -1) {
+                        port = url.getPort();
+                    }
+                } catch (MalformedURLException e) {}
+
+                String databaseCallbackString =
+                        "UI DELEGATE DATABASE CALLBACK: " +
+                        "exceededDatabaseQuotaForSecurityOrigin:{" + protocol +
+                        ", " + host + ", " + port + "} database:" +
+                        databaseIdentifier + "\n";
+                Log.v(LOGTAG, "LOG: "+databaseCallbackString);
+                mDatabaseCallbackStrings.append(databaseCallbackString);
+            }
+            // Give 5MB more quota.
+            callback.updateQuota(currentQuota + 1024 * 1024 * 5);
+        }
+
+        @Override
+        public void addMessageToConsole(String message, int lineNumber,
+                String sourceID) {
+            if (mConsoleMessages == null) {
+                mConsoleMessages = new StringBuffer();
+            }
+            String consoleMessage = "CONSOLE MESSAGE: line "
+                    + lineNumber +": "+ message +"\n";
+            mConsoleMessages.append(consoleMessage);
+            Log.v(LOGTAG, "LOG: "+consoleMessage);
+        }
+
+        @Override
+        public boolean onCreateWindow(WebView view, boolean dialog,
+                boolean userGesture, Message resultMsg) {
+            if (!mCanOpenWindows) {
+                return false;
+            }
+
+            // We never display the new window, just create the view and
+            // allow it's content to execute and be recorded by the test
+            // runner.
+
+            WebView newWindowView = new WebView(TestShellActivity.this);
+            setupWebViewForLayoutTests(newWindowView, mCallbackProxy);
+            WebView.WebViewTransport transport =
+                    (WebView.WebViewTransport) resultMsg.obj;
+            transport.setWebView(newWindowView);
+            resultMsg.sendToTarget();
+            return true;
+        }
     };
     
     private void resetTestStatus() {
@@ -442,9 +523,32 @@
         mTimedOut = false;
         mDumpTitleChanges = false;
         mRequestedWebKitData = false;
+        mDumpDatabaseCallbacks = false;
+        mCanOpenWindows = false;
         mEventSender.resetMouse();
     }
-    
+
+    private void setupWebViewForLayoutTests(WebView webview, CallbackProxy callbackProxy) {
+        if (webview == null) {
+            return;
+        }
+
+        WebSettings settings = webview.getSettings();
+        settings.setJavaScriptEnabled(true);
+        settings.setJavaScriptCanOpenWindowsAutomatically(true);
+        settings.setSupportMultipleWindows(true);
+        settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL);
+        settings.setDatabaseEnabled(true);
+        settings.setDatabasePath(getDir("databases",0).getAbsolutePath());
+        settings.setDomStorageEnabled(true);
+
+        webview.addJavascriptInterface(callbackProxy, "layoutTestController");
+        webview.addJavascriptInterface(callbackProxy, "eventSender");
+
+        webview.setWebChromeClient(mChromeClient);
+        webview.setWebViewClient(mViewClient);
+    }
+
     private WebView mWebView;
     private WebViewEventSender mEventSender;
     private AsyncHandler mHandler;
@@ -470,6 +574,10 @@
     private StringBuffer mDialogStrings;
     private boolean mKeepWebHistory;
     private Vector mWebHistory;
+    private boolean mDumpDatabaseCallbacks;
+    private StringBuffer mDatabaseCallbackStrings;
+    private StringBuffer mConsoleMessages;
+    private boolean mCanOpenWindows;
 
     static final String TIMEOUT_STR = "**Test timeout";
     
diff --git a/tests/backup/src/com/android/backuptest/BackupTestActivity.java b/tests/backup/src/com/android/backuptest/BackupTestActivity.java
index f0c3f93..7f30c91 100644
--- a/tests/backup/src/com/android/backuptest/BackupTestActivity.java
+++ b/tests/backup/src/com/android/backuptest/BackupTestActivity.java
@@ -17,12 +17,11 @@
 package com.android.backuptest;
 
 import android.app.ListActivity;
+import android.backup.BackupHelperDispatcher;
 import android.backup.BackupDataInput;
 import android.backup.BackupDataOutput;
 import android.backup.BackupManager;
 import android.backup.FileBackupHelper;
-import android.backup.FileRestoreHelper;
-import android.backup.RestoreHelperDispatcher;
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.os.Bundle;
@@ -142,10 +141,10 @@
                             ParcelFileDescriptor.MODE_READ_WRITE|ParcelFileDescriptor.MODE_CREATE|
                             ParcelFileDescriptor.MODE_TRUNCATE);
                     FileBackupHelper h = new FileBackupHelper(BackupTestActivity.this,
-                            "FileBackupHelper");
+                            new String[] { "a", "empty" });
                     FileOutputStream dataFile = openFileOutput("backup_test", MODE_WORLD_READABLE);
                     BackupDataOutput data = new BackupDataOutput(dataFile.getFD());
-                    h.performBackup(null, data, state, new String[] { "a", "empty" });
+                    h.performBackup(null, data, state);
                     dataFile.close();
                     state.close();
                 } catch (IOException ex) {
@@ -156,16 +155,17 @@
         new Test("Restore Helpers") {
             void run() {
                 try {
-                    RestoreHelperDispatcher dispatch = new RestoreHelperDispatcher();
-                    dispatch.addHelper("FileBackupHelper",
-                            new FileRestoreHelper(BackupTestActivity.this));
+                    BackupHelperDispatcher dispatch = new BackupHelperDispatcher();
+                    dispatch.addHelper("", new FileBackupHelper(BackupTestActivity.this,
+                            new String[] { "a", "empty" }));
                     FileInputStream dataFile = openFileInput("backup_test");
                     BackupDataInput data = new BackupDataInput(dataFile.getFD());
                     ParcelFileDescriptor state = ParcelFileDescriptor.open(
                             new File(getFilesDir(), "restore_state"),
                             ParcelFileDescriptor.MODE_READ_WRITE|ParcelFileDescriptor.MODE_CREATE|
                             ParcelFileDescriptor.MODE_TRUNCATE);
-                    dispatch.dispatch(data, state);
+                    // TODO: a more plausable synthetic stored-data version number
+                    dispatch.performRestore(data, 0, state);
                     dataFile.close();
                     state.close();
                 } catch (IOException ex) {
diff --git a/tests/backup/src/com/android/backuptest/BackupTestAgent.java b/tests/backup/src/com/android/backuptest/BackupTestAgent.java
index 0da4151..c6acc66 100644
--- a/tests/backup/src/com/android/backuptest/BackupTestAgent.java
+++ b/tests/backup/src/com/android/backuptest/BackupTestAgent.java
@@ -16,46 +16,13 @@
 
 package com.android.backuptest;
 
-import android.app.BackupAgent;
-import android.backup.BackupDataInput;
-import android.backup.BackupDataOutput;
+import android.backup.BackupHelperAgent;
 import android.backup.FileBackupHelper;
-import android.backup.FileRestoreHelper;
-import android.backup.RestoreHelperDispatcher;
-import android.os.ParcelFileDescriptor;
-import android.util.Log;
 
-import java.io.IOException;
-
-public class BackupTestAgent extends BackupAgent
+public class BackupTestAgent extends BackupHelperAgent
 {
-    static final String TAG = "BackupTestAgent";
-
-    static final String SHARED_PREFS = "shared_prefs";
-    static final String DATA_FILES = "data_files";
-    static final String[] FILES = new String[] {
-                    BackupTestActivity.FILE_NAME
-                };
-
-    @Override
-    public void onBackup(ParcelFileDescriptor oldState, BackupDataOutput data,
-             ParcelFileDescriptor newState) {
-        Log.d(TAG, "onBackup");
-
-        (new FileBackupHelper(this, DATA_FILES)).performBackup(oldState, data, newState, FILES);
-    }
-
-    @Override
-    public void onRestore(BackupDataInput data, ParcelFileDescriptor newState)
-            throws IOException {
-        Log.d(TAG, "onRestore");
-
-        RestoreHelperDispatcher dispatch = new RestoreHelperDispatcher();
-
-        // dispatch.addHelper(SHARED_PREFS, new SharedPrefsRestoreHelper(this));
-        dispatch.addHelper(DATA_FILES, new FileRestoreHelper(this));
-
-        dispatch.dispatch(data, newState);
+    public void onCreate() {
+        addHelper("data_files", new FileBackupHelper(this, BackupTestActivity.FILE_NAME));
     }
 }
 
diff --git a/tests/permission/src/com/android/framework/permission/tests/HardwareServicePermissionTest.java b/tests/permission/src/com/android/framework/permission/tests/HardwareServicePermissionTest.java
index dc6860a..719e758 100644
--- a/tests/permission/src/com/android/framework/permission/tests/HardwareServicePermissionTest.java
+++ b/tests/permission/src/com/android/framework/permission/tests/HardwareServicePermissionTest.java
@@ -22,10 +22,12 @@
 import android.os.IHardwareService;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.test.suitebuilder.annotation.SmallTest;
 
 /**
  * Verify that Hardware apis cannot be called without required permissions.
  */
+@SmallTest
 public class HardwareServicePermissionTest extends TestCase {
 
     private IHardwareService mHardwareService;