Merge change 20918

* changes:
  Wrap up the stress test into a single script make test_restore.sh return a value signifying success or failure
diff --git a/api/current.xml b/api/current.xml
index 69d4d5c..8682b15 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -1453,7 +1453,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="17432609"
+ value="17432583"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -1464,7 +1464,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="17432611"
+ value="17432585"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -1475,7 +1475,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="17432612"
+ value="17432586"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -1493,292 +1493,6 @@
  visibility="public"
 >
 </field>
-<field name="donut_resource_pad1"
- type="int"
- transient="false"
- volatile="false"
- value="17432608"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad10"
- type="int"
- transient="false"
- volatile="false"
- value="17432599"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad11"
- type="int"
- transient="false"
- volatile="false"
- value="17432598"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad12"
- type="int"
- transient="false"
- volatile="false"
- value="17432597"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad13"
- type="int"
- transient="false"
- volatile="false"
- value="17432596"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad14"
- type="int"
- transient="false"
- volatile="false"
- value="17432595"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad15"
- type="int"
- transient="false"
- volatile="false"
- value="17432594"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad16"
- type="int"
- transient="false"
- volatile="false"
- value="17432593"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad17"
- type="int"
- transient="false"
- volatile="false"
- value="17432592"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad18"
- type="int"
- transient="false"
- volatile="false"
- value="17432591"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad19"
- type="int"
- transient="false"
- volatile="false"
- value="17432590"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad2"
- type="int"
- transient="false"
- volatile="false"
- value="17432607"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad20"
- type="int"
- transient="false"
- volatile="false"
- value="17432589"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad21"
- type="int"
- transient="false"
- volatile="false"
- value="17432588"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad22"
- type="int"
- transient="false"
- volatile="false"
- value="17432587"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad23"
- type="int"
- transient="false"
- volatile="false"
- value="17432586"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad24"
- type="int"
- transient="false"
- volatile="false"
- value="17432585"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad25"
- type="int"
- transient="false"
- volatile="false"
- value="17432584"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad26"
- type="int"
- transient="false"
- volatile="false"
- value="17432583"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad3"
- type="int"
- transient="false"
- volatile="false"
- value="17432606"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad4"
- type="int"
- transient="false"
- volatile="false"
- value="17432605"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad5"
- type="int"
- transient="false"
- volatile="false"
- value="17432604"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad6"
- type="int"
- transient="false"
- volatile="false"
- value="17432603"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad7"
- type="int"
- transient="false"
- volatile="false"
- value="17432602"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad8"
- type="int"
- transient="false"
- volatile="false"
- value="17432601"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad9"
- type="int"
- transient="false"
- volatile="false"
- value="17432600"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="fade_in"
  type="int"
  transient="false"
@@ -1805,7 +1519,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="17432613"
+ value="17432587"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -1816,7 +1530,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="17432610"
+ value="17432584"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -1862,138 +1576,6 @@
  visibility="public"
 >
 </constructor>
-<field name="donut_resource_pad1"
- type="int"
- transient="false"
- volatile="false"
- value="17235984"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad10"
- type="int"
- transient="false"
- volatile="false"
- value="17235975"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad11"
- type="int"
- transient="false"
- volatile="false"
- value="17235974"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad12"
- type="int"
- transient="false"
- volatile="false"
- value="17235973"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad2"
- type="int"
- transient="false"
- volatile="false"
- value="17235983"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad3"
- type="int"
- transient="false"
- volatile="false"
- value="17235982"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad4"
- type="int"
- transient="false"
- volatile="false"
- value="17235981"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad5"
- type="int"
- transient="false"
- volatile="false"
- value="17235980"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad6"
- type="int"
- transient="false"
- volatile="false"
- value="17235979"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad7"
- type="int"
- transient="false"
- volatile="false"
- value="17235978"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad8"
- type="int"
- transient="false"
- volatile="false"
- value="17235977"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad9"
- type="int"
- transient="false"
- volatile="false"
- value="17235976"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="emailAddressTypes"
  type="int"
  transient="false"
@@ -2081,7 +1663,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843424"
+ value="16843406"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -3082,7 +2664,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843425"
+ value="16843407"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -3386,204 +2968,6 @@
  visibility="public"
 >
 </field>
-<field name="donut_resource_pad1"
- type="int"
- transient="false"
- volatile="false"
- value="16843423"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad10"
- type="int"
- transient="false"
- volatile="false"
- value="16843414"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad11"
- type="int"
- transient="false"
- volatile="false"
- value="16843413"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad12"
- type="int"
- transient="false"
- volatile="false"
- value="16843412"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad13"
- type="int"
- transient="false"
- volatile="false"
- value="16843411"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad14"
- type="int"
- transient="false"
- volatile="false"
- value="16843410"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad15"
- type="int"
- transient="false"
- volatile="false"
- value="16843409"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad16"
- type="int"
- transient="false"
- volatile="false"
- value="16843408"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad17"
- type="int"
- transient="false"
- volatile="false"
- value="16843407"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad18"
- type="int"
- transient="false"
- volatile="false"
- value="16843406"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad2"
- type="int"
- transient="false"
- volatile="false"
- value="16843422"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad3"
- type="int"
- transient="false"
- volatile="false"
- value="16843421"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad4"
- type="int"
- transient="false"
- volatile="false"
- value="16843420"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad5"
- type="int"
- transient="false"
- volatile="false"
- value="16843419"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad6"
- type="int"
- transient="false"
- volatile="false"
- value="16843418"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad7"
- type="int"
- transient="false"
- volatile="false"
- value="16843417"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad8"
- type="int"
- transient="false"
- volatile="false"
- value="16843416"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad9"
- type="int"
- transient="false"
- volatile="false"
- value="16843415"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="drawSelectorOnTop"
  type="int"
  transient="false"
@@ -9374,7 +8758,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843426"
+ value="16843408"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -9558,347 +8942,6 @@
  visibility="public"
 >
 </field>
-<field name="donut_resource_pad1"
- type="int"
- transient="false"
- volatile="false"
- value="17170480"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad10"
- type="int"
- transient="false"
- volatile="false"
- value="17170471"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad11"
- type="int"
- transient="false"
- volatile="false"
- value="17170470"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad12"
- type="int"
- transient="false"
- volatile="false"
- value="17170469"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad13"
- type="int"
- transient="false"
- volatile="false"
- value="17170468"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad14"
- type="int"
- transient="false"
- volatile="false"
- value="17170467"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad15"
- type="int"
- transient="false"
- volatile="false"
- value="17170466"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad16"
- type="int"
- transient="false"
- volatile="false"
- value="17170465"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad17"
- type="int"
- transient="false"
- volatile="false"
- value="17170464"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad18"
- type="int"
- transient="false"
- volatile="false"
- value="17170463"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad19"
- type="int"
- transient="false"
- volatile="false"
- value="17170462"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad2"
- type="int"
- transient="false"
- volatile="false"
- value="17170479"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad20"
- type="int"
- transient="false"
- volatile="false"
- value="17170461"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad21"
- type="int"
- transient="false"
- volatile="false"
- value="17170460"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad22"
- type="int"
- transient="false"
- volatile="false"
- value="17170459"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad23"
- type="int"
- transient="false"
- volatile="false"
- value="17170458"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad24"
- type="int"
- transient="false"
- volatile="false"
- value="17170457"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad25"
- type="int"
- transient="false"
- volatile="false"
- value="17170456"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad26"
- type="int"
- transient="false"
- volatile="false"
- value="17170455"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad27"
- type="int"
- transient="false"
- volatile="false"
- value="17170454"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad28"
- type="int"
- transient="false"
- volatile="false"
- value="17170453"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad29"
- type="int"
- transient="false"
- volatile="false"
- value="17170452"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad3"
- type="int"
- transient="false"
- volatile="false"
- value="17170478"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad30"
- type="int"
- transient="false"
- volatile="false"
- value="17170451"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad31"
- type="int"
- transient="false"
- volatile="false"
- value="17170450"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad4"
- type="int"
- transient="false"
- volatile="false"
- value="17170477"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad5"
- type="int"
- transient="false"
- volatile="false"
- value="17170476"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad6"
- type="int"
- transient="false"
- volatile="false"
- value="17170475"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad7"
- type="int"
- transient="false"
- volatile="false"
- value="17170474"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad8"
- type="int"
- transient="false"
- volatile="false"
- value="17170473"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad9"
- type="int"
- transient="false"
- volatile="false"
- value="17170472"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="primary_text_dark"
  type="int"
  transient="false"
@@ -10081,160 +9124,6 @@
  visibility="public"
 >
 </field>
-<field name="donut_resource_pad1"
- type="int"
- transient="false"
- volatile="false"
- value="17104912"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad10"
- type="int"
- transient="false"
- volatile="false"
- value="17104903"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad11"
- type="int"
- transient="false"
- volatile="false"
- value="17104902"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad12"
- type="int"
- transient="false"
- volatile="false"
- value="17104901"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad13"
- type="int"
- transient="false"
- volatile="false"
- value="17104900"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad14"
- type="int"
- transient="false"
- volatile="false"
- value="17104899"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad2"
- type="int"
- transient="false"
- volatile="false"
- value="17104911"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad3"
- type="int"
- transient="false"
- volatile="false"
- value="17104910"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad4"
- type="int"
- transient="false"
- volatile="false"
- value="17104909"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad5"
- type="int"
- transient="false"
- volatile="false"
- value="17104908"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad6"
- type="int"
- transient="false"
- volatile="false"
- value="17104907"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad7"
- type="int"
- transient="false"
- volatile="false"
- value="17104906"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad8"
- type="int"
- transient="false"
- volatile="false"
- value="17104905"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad9"
- type="int"
- transient="false"
- volatile="false"
- value="17104904"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="thumbnail_height"
  type="int"
  transient="false"
@@ -10549,468 +9438,6 @@
  visibility="public"
 >
 </field>
-<field name="donut_resource_pad1"
- type="int"
- transient="false"
- volatile="false"
- value="17301712"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad10"
- type="int"
- transient="false"
- volatile="false"
- value="17301703"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad11"
- type="int"
- transient="false"
- volatile="false"
- value="17301702"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad12"
- type="int"
- transient="false"
- volatile="false"
- value="17301701"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad13"
- type="int"
- transient="false"
- volatile="false"
- value="17301700"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad14"
- type="int"
- transient="false"
- volatile="false"
- value="17301699"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad15"
- type="int"
- transient="false"
- volatile="false"
- value="17301698"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad16"
- type="int"
- transient="false"
- volatile="false"
- value="17301697"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad17"
- type="int"
- transient="false"
- volatile="false"
- value="17301696"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad18"
- type="int"
- transient="false"
- volatile="false"
- value="17301695"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad19"
- type="int"
- transient="false"
- volatile="false"
- value="17301694"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad2"
- type="int"
- transient="false"
- volatile="false"
- value="17301711"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad20"
- type="int"
- transient="false"
- volatile="false"
- value="17301693"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad21"
- type="int"
- transient="false"
- volatile="false"
- value="17301692"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad22"
- type="int"
- transient="false"
- volatile="false"
- value="17301691"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad23"
- type="int"
- transient="false"
- volatile="false"
- value="17301690"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad24"
- type="int"
- transient="false"
- volatile="false"
- value="17301689"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad25"
- type="int"
- transient="false"
- volatile="false"
- value="17301688"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad26"
- type="int"
- transient="false"
- volatile="false"
- value="17301687"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad27"
- type="int"
- transient="false"
- volatile="false"
- value="17301686"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad28"
- type="int"
- transient="false"
- volatile="false"
- value="17301685"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad29"
- type="int"
- transient="false"
- volatile="false"
- value="17301684"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad3"
- type="int"
- transient="false"
- volatile="false"
- value="17301710"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad30"
- type="int"
- transient="false"
- volatile="false"
- value="17301683"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad31"
- type="int"
- transient="false"
- volatile="false"
- value="17301682"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad32"
- type="int"
- transient="false"
- volatile="false"
- value="17301681"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad33"
- type="int"
- transient="false"
- volatile="false"
- value="17301680"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad34"
- type="int"
- transient="false"
- volatile="false"
- value="17301679"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad35"
- type="int"
- transient="false"
- volatile="false"
- value="17301678"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad36"
- type="int"
- transient="false"
- volatile="false"
- value="17301677"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad37"
- type="int"
- transient="false"
- volatile="false"
- value="17301676"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad38"
- type="int"
- transient="false"
- volatile="false"
- value="17301675"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad39"
- type="int"
- transient="false"
- volatile="false"
- value="17301674"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad4"
- type="int"
- transient="false"
- volatile="false"
- value="17301709"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad40"
- type="int"
- transient="false"
- volatile="false"
- value="17301673"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad41"
- type="int"
- transient="false"
- volatile="false"
- value="17301672"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad42"
- type="int"
- transient="false"
- volatile="false"
- value="17301671"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad5"
- type="int"
- transient="false"
- volatile="false"
- value="17301708"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad6"
- type="int"
- transient="false"
- volatile="false"
- value="17301707"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad7"
- type="int"
- transient="false"
- volatile="false"
- value="17301706"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad8"
- type="int"
- transient="false"
- volatile="false"
- value="17301705"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad9"
- type="int"
- transient="false"
- volatile="false"
- value="17301704"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="edit_text"
  type="int"
  transient="false"
@@ -12346,7 +10773,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="17301713"
+ value="17301671"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -12357,7 +10784,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="17301714"
+ value="17301672"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -12678,248 +11105,6 @@
  visibility="public"
 >
 </field>
-<field name="donut_resource_pad1"
- type="int"
- transient="false"
- volatile="false"
- value="16908352"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad10"
- type="int"
- transient="false"
- volatile="false"
- value="16908343"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad11"
- type="int"
- transient="false"
- volatile="false"
- value="16908342"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad12"
- type="int"
- transient="false"
- volatile="false"
- value="16908341"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad13"
- type="int"
- transient="false"
- volatile="false"
- value="16908340"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad14"
- type="int"
- transient="false"
- volatile="false"
- value="16908339"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad15"
- type="int"
- transient="false"
- volatile="false"
- value="16908338"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad16"
- type="int"
- transient="false"
- volatile="false"
- value="16908337"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad17"
- type="int"
- transient="false"
- volatile="false"
- value="16908336"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad18"
- type="int"
- transient="false"
- volatile="false"
- value="16908335"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad19"
- type="int"
- transient="false"
- volatile="false"
- value="16908334"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad2"
- type="int"
- transient="false"
- volatile="false"
- value="16908351"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad20"
- type="int"
- transient="false"
- volatile="false"
- value="16908333"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad21"
- type="int"
- transient="false"
- volatile="false"
- value="16908332"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad22"
- type="int"
- transient="false"
- volatile="false"
- value="16908331"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad3"
- type="int"
- transient="false"
- volatile="false"
- value="16908350"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad4"
- type="int"
- transient="false"
- volatile="false"
- value="16908349"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad5"
- type="int"
- transient="false"
- volatile="false"
- value="16908348"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad6"
- type="int"
- transient="false"
- volatile="false"
- value="16908347"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad7"
- type="int"
- transient="false"
- volatile="false"
- value="16908346"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad8"
- type="int"
- transient="false"
- volatile="false"
- value="16908345"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad9"
- type="int"
- transient="false"
- volatile="false"
- value="16908344"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="edit"
  type="int"
  transient="false"
@@ -13311,160 +11496,6 @@
  visibility="public"
 >
 </field>
-<field name="donut_resource_pad1"
- type="int"
- transient="false"
- volatile="false"
- value="17694736"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad10"
- type="int"
- transient="false"
- volatile="false"
- value="17694727"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad11"
- type="int"
- transient="false"
- volatile="false"
- value="17694726"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad12"
- type="int"
- transient="false"
- volatile="false"
- value="17694725"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad13"
- type="int"
- transient="false"
- volatile="false"
- value="17694724"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad14"
- type="int"
- transient="false"
- volatile="false"
- value="17694723"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad2"
- type="int"
- transient="false"
- volatile="false"
- value="17694735"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad3"
- type="int"
- transient="false"
- volatile="false"
- value="17694734"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad4"
- type="int"
- transient="false"
- volatile="false"
- value="17694733"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad5"
- type="int"
- transient="false"
- volatile="false"
- value="17694732"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad6"
- type="int"
- transient="false"
- volatile="false"
- value="17694731"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad7"
- type="int"
- transient="false"
- volatile="false"
- value="17694730"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad8"
- type="int"
- transient="false"
- volatile="false"
- value="17694729"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad9"
- type="int"
- transient="false"
- volatile="false"
- value="17694728"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 </class>
 <class name="R.layout"
  extends="java.lang.Object"
@@ -13504,149 +11535,6 @@
  visibility="public"
 >
 </field>
-<field name="donut_resource_pad1"
- type="int"
- transient="false"
- volatile="false"
- value="17367072"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad10"
- type="int"
- transient="false"
- volatile="false"
- value="17367063"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad11"
- type="int"
- transient="false"
- volatile="false"
- value="17367062"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad12"
- type="int"
- transient="false"
- volatile="false"
- value="17367061"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad13"
- type="int"
- transient="false"
- volatile="false"
- value="17367060"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad2"
- type="int"
- transient="false"
- volatile="false"
- value="17367071"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad3"
- type="int"
- transient="false"
- volatile="false"
- value="17367070"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad4"
- type="int"
- transient="false"
- volatile="false"
- value="17367069"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad5"
- type="int"
- transient="false"
- volatile="false"
- value="17367068"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad6"
- type="int"
- transient="false"
- volatile="false"
- value="17367067"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad7"
- type="int"
- transient="false"
- volatile="false"
- value="17367066"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad8"
- type="int"
- transient="false"
- volatile="false"
- value="17367065"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad9"
- type="int"
- transient="false"
- volatile="false"
- value="17367064"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="expandable_list_content"
  type="int"
  transient="false"
@@ -14017,303 +11905,6 @@
  visibility="public"
 >
 </field>
-<field name="donut_resource_pad1"
- type="int"
- transient="false"
- volatile="false"
- value="17039408"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad10"
- type="int"
- transient="false"
- volatile="false"
- value="17039399"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad11"
- type="int"
- transient="false"
- volatile="false"
- value="17039398"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad12"
- type="int"
- transient="false"
- volatile="false"
- value="17039397"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad13"
- type="int"
- transient="false"
- volatile="false"
- value="17039396"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad14"
- type="int"
- transient="false"
- volatile="false"
- value="17039395"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad15"
- type="int"
- transient="false"
- volatile="false"
- value="17039394"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad16"
- type="int"
- transient="false"
- volatile="false"
- value="17039393"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad17"
- type="int"
- transient="false"
- volatile="false"
- value="17039392"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad18"
- type="int"
- transient="false"
- volatile="false"
- value="17039391"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad19"
- type="int"
- transient="false"
- volatile="false"
- value="17039390"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad2"
- type="int"
- transient="false"
- volatile="false"
- value="17039407"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad20"
- type="int"
- transient="false"
- volatile="false"
- value="17039389"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad21"
- type="int"
- transient="false"
- volatile="false"
- value="17039388"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad22"
- type="int"
- transient="false"
- volatile="false"
- value="17039387"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad23"
- type="int"
- transient="false"
- volatile="false"
- value="17039386"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad24"
- type="int"
- transient="false"
- volatile="false"
- value="17039385"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad25"
- type="int"
- transient="false"
- volatile="false"
- value="17039384"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad26"
- type="int"
- transient="false"
- volatile="false"
- value="17039383"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad27"
- type="int"
- transient="false"
- volatile="false"
- value="17039382"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad3"
- type="int"
- transient="false"
- volatile="false"
- value="17039406"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad4"
- type="int"
- transient="false"
- volatile="false"
- value="17039405"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad5"
- type="int"
- transient="false"
- volatile="false"
- value="17039404"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad6"
- type="int"
- transient="false"
- volatile="false"
- value="17039403"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad7"
- type="int"
- transient="false"
- volatile="false"
- value="17039402"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad8"
- type="int"
- transient="false"
- volatile="false"
- value="17039401"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad9"
- type="int"
- transient="false"
- volatile="false"
- value="17039400"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="emptyPhoneNumber"
  type="int"
  transient="false"
@@ -15017,7 +12608,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973937"
+ value="16973918"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15028,7 +12619,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973938"
+ value="16973919"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15039,7 +12630,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973939"
+ value="16973920"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15497,215 +13088,6 @@
  visibility="public"
 >
 </field>
-<field name="donut_resource_pad1"
- type="int"
- transient="false"
- volatile="false"
- value="16973936"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad10"
- type="int"
- transient="false"
- volatile="false"
- value="16973927"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad11"
- type="int"
- transient="false"
- volatile="false"
- value="16973926"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad12"
- type="int"
- transient="false"
- volatile="false"
- value="16973925"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad13"
- type="int"
- transient="false"
- volatile="false"
- value="16973924"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad14"
- type="int"
- transient="false"
- volatile="false"
- value="16973923"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad15"
- type="int"
- transient="false"
- volatile="false"
- value="16973922"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad16"
- type="int"
- transient="false"
- volatile="false"
- value="16973921"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad17"
- type="int"
- transient="false"
- volatile="false"
- value="16973920"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad18"
- type="int"
- transient="false"
- volatile="false"
- value="16973919"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad19"
- type="int"
- transient="false"
- volatile="false"
- value="16973918"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad2"
- type="int"
- transient="false"
- volatile="false"
- value="16973935"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad3"
- type="int"
- transient="false"
- volatile="false"
- value="16973934"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad4"
- type="int"
- transient="false"
- volatile="false"
- value="16973933"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad5"
- type="int"
- transient="false"
- volatile="false"
- value="16973932"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad6"
- type="int"
- transient="false"
- volatile="false"
- value="16973931"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad7"
- type="int"
- transient="false"
- volatile="false"
- value="16973930"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad8"
- type="int"
- transient="false"
- volatile="false"
- value="16973929"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad9"
- type="int"
- transient="false"
- volatile="false"
- value="16973928"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 </class>
 <class name="R.xml"
  extends="java.lang.Object"
@@ -26818,6 +24200,19 @@
 <exception name="IOException" type="java.io.IOException">
 </exception>
 </method>
+<method name="clearWallpaperOffsets"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="windowToken" type="android.os.IBinder">
+</parameter>
+</method>
 <method name="getDesiredMinimumHeight"
  return="int"
  abstract="false"
@@ -27892,6 +25287,23 @@
 <parameter name="cursor" type="android.database.Cursor">
 </parameter>
 </method>
+<method name="onQueryEntitiesComplete"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+<parameter name="token" type="int">
+</parameter>
+<parameter name="cookie" type="java.lang.Object">
+</parameter>
+<parameter name="iterator" type="android.content.EntityIterator">
+</parameter>
+</method>
 <method name="onUpdateComplete"
  return="void"
  abstract="false"
@@ -27974,6 +25386,29 @@
 <parameter name="orderBy" type="java.lang.String">
 </parameter>
 </method>
+<method name="startQueryEntities"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="token" type="int">
+</parameter>
+<parameter name="cookie" type="java.lang.Object">
+</parameter>
+<parameter name="uri" type="android.net.Uri">
+</parameter>
+<parameter name="selection" type="java.lang.String">
+</parameter>
+<parameter name="selectionArgs" type="java.lang.String[]">
+</parameter>
+<parameter name="orderBy" type="java.lang.String">
+</parameter>
+</method>
 <method name="startUpdate"
  return="void"
  abstract="false"
@@ -40445,6 +37880,21 @@
 <parameter name="pkg2" type="java.lang.String">
 </parameter>
 </method>
+<method name="checkSignatures"
+ return="int"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uid1" type="int">
+</parameter>
+<parameter name="uid2" type="int">
+</parameter>
+</method>
 <method name="clearPackagePreferredActivities"
  return="void"
  abstract="true"
@@ -97295,7 +94745,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="10000"
+ value="4"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -124563,6 +122013,21 @@
 <parameter name="pkg2" type="java.lang.String">
 </parameter>
 </method>
+<method name="checkSignatures"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="uid1" type="int">
+</parameter>
+<parameter name="uid2" type="int">
+</parameter>
+</method>
 <method name="clearPackagePreferredActivities"
  return="void"
  abstract="false"
@@ -130075,6 +127540,16 @@
  visibility="public"
 >
 </field>
+<field name="density"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="drawableState"
  type="int[]"
  transient="false"
@@ -135073,6 +132548,18 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="size" type="int">
+</parameter>
+<parameter name="dip" type="boolean">
+</parameter>
+</constructor>
+<constructor name="AbsoluteSizeSpan"
+ type="android.text.style.AbsoluteSizeSpan"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
 <parameter name="src" type="android.os.Parcel">
 </parameter>
 </constructor>
@@ -135087,6 +132574,17 @@
  visibility="public"
 >
 </method>
+<method name="getDip"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getSize"
  return="int"
  abstract="false"
@@ -136477,6 +133975,41 @@
 </parameter>
 </method>
 </interface>
+<interface name="LineHeightSpan.WithDensity"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.text.style.LineHeightSpan">
+</implements>
+<method name="chooseHeight"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="text" type="java.lang.CharSequence">
+</parameter>
+<parameter name="start" type="int">
+</parameter>
+<parameter name="end" type="int">
+</parameter>
+<parameter name="spanstartv" type="int">
+</parameter>
+<parameter name="v" type="int">
+</parameter>
+<parameter name="fm" type="android.graphics.Paint.FontMetricsInt">
+</parameter>
+<parameter name="paint" type="android.text.TextPaint">
+</parameter>
+</method>
+</interface>
 <class name="MaskFilterSpan"
  extends="android.text.style.CharacterStyle"
  abstract="false"
@@ -165265,14 +162798,14 @@
  abstract="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <constructor name="Plugin"
  type="android.webkit.Plugin"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="name" type="java.lang.String">
@@ -165291,7 +162824,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="context" type="android.content.Context">
@@ -165304,7 +162837,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -165315,7 +162848,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -165326,7 +162859,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -165337,7 +162870,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -165348,7 +162881,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="handler" type="android.webkit.Plugin.PreferencesClickHandler">
@@ -165361,7 +162894,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="description" type="java.lang.String">
@@ -165374,7 +162907,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="fileName" type="java.lang.String">
@@ -165387,7 +162920,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="name" type="java.lang.String">
@@ -165400,7 +162933,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="path" type="java.lang.String">
@@ -165433,14 +162966,14 @@
  abstract="false"
  static="false"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <constructor name="PluginData"
  type="android.webkit.PluginData"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="stream" type="java.io.InputStream">
@@ -165459,7 +162992,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -165470,7 +163003,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -165481,7 +163014,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -165492,7 +163025,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -165502,14 +163035,14 @@
  abstract="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <constructor name="PluginList"
  type="android.webkit.PluginList"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </constructor>
@@ -165520,7 +163053,7 @@
  synchronized="true"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="plugin" type="android.webkit.Plugin">
@@ -165533,7 +163066,7 @@
  synchronized="true"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -165544,7 +163077,7 @@
  synchronized="true"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -165555,7 +163088,7 @@
  synchronized="true"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="context" type="android.content.Context">
@@ -165570,7 +163103,7 @@
  synchronized="true"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="plugin" type="android.webkit.Plugin">
@@ -165847,7 +163380,7 @@
  abstract="true"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <method name="getPluginData"
@@ -165857,7 +163390,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="url" type="java.lang.String">
@@ -165886,7 +163419,7 @@
  abstract="false"
  static="false"
  final="true"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <constructor name="UrlInterceptRegistry"
@@ -165904,7 +163437,7 @@
  synchronized="true"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="url" type="java.lang.String">
@@ -165934,7 +163467,7 @@
  synchronized="true"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="handler" type="android.webkit.UrlInterceptHandler">
@@ -165947,7 +163480,7 @@
  synchronized="true"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="disabled" type="boolean">
@@ -165960,7 +163493,7 @@
  synchronized="true"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="handler" type="android.webkit.UrlInterceptHandler">
@@ -165973,7 +163506,7 @@
  synchronized="true"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -167967,7 +165500,7 @@
  synchronized="true"
  static="true"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
@@ -168260,7 +165793,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="reloadOpenPages" type="boolean">
@@ -277693,24 +275226,6 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="isDaemon" type="boolean">
-</parameter>
-</constructor>
-<constructor name="Timer"
- type="java.util.Timer"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</constructor>
-<constructor name="Timer"
- type="java.util.Timer"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
 <parameter name="name" type="java.lang.String">
 </parameter>
 <parameter name="isDaemon" type="boolean">
@@ -277726,6 +275241,24 @@
 <parameter name="name" type="java.lang.String">
 </parameter>
 </constructor>
+<constructor name="Timer"
+ type="java.util.Timer"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="isDaemon" type="boolean">
+</parameter>
+</constructor>
+<constructor name="Timer"
+ type="java.util.Timer"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
 <method name="cancel"
  return="void"
  abstract="false"
diff --git a/camera/libcameraservice/Android.mk b/camera/libcameraservice/Android.mk
index be78a62..ecaebff 100644
--- a/camera/libcameraservice/Android.mk
+++ b/camera/libcameraservice/Android.mk
@@ -25,6 +25,10 @@
 
 LOCAL_MODULE:= libcamerastub
 
+ifeq ($(TARGET_SIMULATOR),true)
+LOCAL_CFLAGS += -DSINGLE_PROCESS
+endif
+
 LOCAL_SHARED_LIBRARIES:= libui
 
 include $(BUILD_STATIC_LIBRARY)
@@ -48,7 +52,11 @@
 
 LOCAL_MODULE:= libcameraservice
 
-LOCAL_CFLAGS+=-DLOG_TAG=\"CameraService\"
+LOCAL_CFLAGS += -DLOG_TAG=\"CameraService\"
+
+ifeq ($(TARGET_SIMULATOR),true)
+LOCAL_CFLAGS += -DSINGLE_PROCESS
+endif
 
 ifeq ($(USE_CAMERA_STUB), true)
 LOCAL_STATIC_LIBRARIES += libcamerastub
diff --git a/camera/libcameraservice/CameraHardwareStub.cpp b/camera/libcameraservice/CameraHardwareStub.cpp
index a7af57c..24496bb 100644
--- a/camera/libcameraservice/CameraHardwareStub.cpp
+++ b/camera/libcameraservice/CameraHardwareStub.cpp
@@ -33,13 +33,11 @@
                     mRawHeap(0),
                     mFakeCamera(0),
                     mPreviewFrameSize(0),
-                    mRawPictureCallback(0),
-                    mJpegPictureCallback(0),
-                    mPictureCallbackCookie(0),
-                    mPreviewCallback(0),
-                    mPreviewCallbackCookie(0),
-                    mAutoFocusCallback(0),
-                    mAutoFocusCallbackCookie(0),
+                    mNotifyCb(0),
+                    mDataCb(0),
+                    mDataCbTimestamp(0),
+                    mCallbackCookie(0),
+                    mMsgEnabled(0),
                     mCurrentPreviewFrame(0)
 {
     initDefaultParameters();
@@ -112,6 +110,36 @@
     return mRawHeap;
 }
 
+void CameraHardwareStub::setCallbacks(notify_callback notify_cb,
+                                      data_callback data_cb,
+                                      data_callback_timestamp data_cb_timestamp,
+                                      void* user)
+{
+    Mutex::Autolock lock(mLock);
+    mNotifyCb = notify_cb;
+    mDataCb = data_cb;
+    mDataCbTimestamp = data_cb_timestamp;
+    mCallbackCookie = user;
+}
+
+void CameraHardwareStub::enableMsgType(int32_t msgType)
+{
+    Mutex::Autolock lock(mLock);
+    mMsgEnabled |= msgType;
+}
+
+void CameraHardwareStub::disableMsgType(int32_t msgType)
+{
+    Mutex::Autolock lock(mLock);
+    mMsgEnabled &= ~msgType;
+}
+
+bool CameraHardwareStub::msgTypeEnabled(int32_t msgType)
+{
+    Mutex::Autolock lock(mLock);
+    return (mMsgEnabled & msgType);
+}
+
 // ---------------------------------------------------------------------------
 
 int CameraHardwareStub::previewThread()
@@ -150,7 +178,8 @@
         //LOGV("previewThread: generated frame to buffer %d", mCurrentPreviewFrame);
         
         // Notify the client of a new frame.
-        mPreviewCallback(buffer, mPreviewCallbackCookie);
+        if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)
+            mDataCb(CAMERA_MSG_PREVIEW_FRAME, buffer, mCallbackCookie);
     
         // Advance the buffer pointer.
         mCurrentPreviewFrame = (mCurrentPreviewFrame + 1) % kBufferCount;
@@ -162,15 +191,13 @@
     return NO_ERROR;
 }
 
-status_t CameraHardwareStub::startPreview(preview_callback cb, void* user)
+status_t CameraHardwareStub::startPreview()
 {
     Mutex::Autolock lock(mLock);
     if (mPreviewThread != 0) {
         // already running
         return INVALID_OPERATION;
     }
-    mPreviewCallback = cb;
-    mPreviewCallbackCookie = user;
     mPreviewThread = new PreviewThread(this);
     return NO_ERROR;
 }
@@ -197,7 +224,7 @@
     return mPreviewThread != 0;
 }
 
-status_t CameraHardwareStub::startRecording(recording_callback cb, void* user)
+status_t CameraHardwareStub::startRecording()
 {
     return UNKNOWN_ERROR;
 }
@@ -225,25 +252,14 @@
 
 int CameraHardwareStub::autoFocusThread()
 {
-    if (mAutoFocusCallback != NULL) {
-        mAutoFocusCallback(true, mAutoFocusCallbackCookie);
-        mAutoFocusCallback = NULL;
-        return NO_ERROR;
-    }
-    return UNKNOWN_ERROR;
+    if (mMsgEnabled & CAMERA_MSG_FOCUS)
+        mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie);
+    return NO_ERROR;
 }
 
-status_t CameraHardwareStub::autoFocus(autofocus_callback af_cb,
-                                       void *user)
+status_t CameraHardwareStub::autoFocus()
 {
     Mutex::Autolock lock(mLock);
-
-    if (mAutoFocusCallback != NULL) {
-        return mAutoFocusCallback == af_cb ? NO_ERROR : INVALID_OPERATION;
-    }
-
-    mAutoFocusCallback = af_cb;
-    mAutoFocusCallbackCookie = user;
     if (createThread(beginAutoFocusThread, this) == false)
         return UNKNOWN_ERROR;
     return NO_ERROR;
@@ -257,10 +273,10 @@
 
 int CameraHardwareStub::pictureThread()
 {
-    if (mShutterCallback)
-        mShutterCallback(mPictureCallbackCookie);
+    if (mMsgEnabled & CAMERA_MSG_SHUTTER)
+        mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie);
 
-    if (mRawPictureCallback) {
+    if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE) {
         //FIXME: use a canned YUV image!
         // In the meantime just make another fake camera picture.
         int w, h;
@@ -268,42 +284,28 @@
         sp<MemoryBase> mem = new MemoryBase(mRawHeap, 0, w * 2 * h);
         FakeCamera cam(w, h);
         cam.getNextFrameAsYuv422((uint8_t *)mRawHeap->base());
-        if (mRawPictureCallback)
-            mRawPictureCallback(mem, mPictureCallbackCookie);
+        mDataCb(CAMERA_MSG_RAW_IMAGE, mem, mCallbackCookie);
     }
 
-    if (mJpegPictureCallback) {
+    if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) {
         sp<MemoryHeapBase> heap = new MemoryHeapBase(kCannedJpegSize);
         sp<MemoryBase> mem = new MemoryBase(heap, 0, kCannedJpegSize);
         memcpy(heap->base(), kCannedJpeg, kCannedJpegSize);
-        if (mJpegPictureCallback)
-            mJpegPictureCallback(mem, mPictureCallbackCookie);
+        mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mem, mCallbackCookie);
     }
     return NO_ERROR;
 }
 
-status_t CameraHardwareStub::takePicture(shutter_callback shutter_cb,
-                                         raw_callback raw_cb,
-                                         jpeg_callback jpeg_cb,
-                                         void* user)
+status_t CameraHardwareStub::takePicture()
 {
     stopPreview();
-    mShutterCallback = shutter_cb;
-    mRawPictureCallback = raw_cb;
-    mJpegPictureCallback = jpeg_cb;
-    mPictureCallbackCookie = user;
     if (createThread(beginPictureThread, this) == false)
         return -1;
     return NO_ERROR;
 }
 
-status_t CameraHardwareStub::cancelPicture(bool cancel_shutter,
-                                           bool cancel_raw,
-                                           bool cancel_jpeg)
+status_t CameraHardwareStub::cancelPicture()
 {
-    if (cancel_shutter) mShutterCallback = NULL;
-    if (cancel_raw) mRawPictureCallback = NULL;
-    if (cancel_jpeg) mJpegPictureCallback = NULL;
     return NO_ERROR;
 }
 
diff --git a/camera/libcameraservice/CameraHardwareStub.h b/camera/libcameraservice/CameraHardwareStub.h
index efae935..000906a 100644
--- a/camera/libcameraservice/CameraHardwareStub.h
+++ b/camera/libcameraservice/CameraHardwareStub.h
@@ -32,23 +32,27 @@
     virtual sp<IMemoryHeap> getPreviewHeap() const;
     virtual sp<IMemoryHeap> getRawHeap() const;
 
-    virtual status_t    startPreview(preview_callback cb, void* user);
+    virtual void        setCallbacks(notify_callback notify_cb,
+                                     data_callback data_cb,
+                                     data_callback_timestamp data_cb_timestamp,
+                                     void* user);
+
+    virtual void        enableMsgType(int32_t msgType);
+    virtual void        disableMsgType(int32_t msgType);
+    virtual bool        msgTypeEnabled(int32_t msgType);
+
+    virtual status_t    startPreview();
     virtual void        stopPreview();
     virtual bool        previewEnabled();
 
-    virtual status_t    startRecording(recording_callback cb, void* user);
+    virtual status_t    startRecording();
     virtual void        stopRecording();
     virtual bool        recordingEnabled();
     virtual void        releaseRecordingFrame(const sp<IMemory>& mem);
 
-    virtual status_t    autoFocus(autofocus_callback, void *user);
-    virtual status_t    takePicture(shutter_callback,
-                                    raw_callback,
-                                    jpeg_callback,
-                                    void* user);
-    virtual status_t    cancelPicture(bool cancel_shutter,
-                                      bool cancel_raw,
-                                      bool cancel_jpeg);
+    virtual status_t    autoFocus();
+    virtual status_t    takePicture();
+    virtual status_t    cancelPicture();
     virtual status_t    dump(int fd, const Vector<String16>& args) const;
     virtual status_t    setParameters(const CameraParameters& params);
     virtual CameraParameters  getParameters() const;
@@ -67,8 +71,15 @@
     class PreviewThread : public Thread {
         CameraHardwareStub* mHardware;
     public:
-        PreviewThread(CameraHardwareStub* hw)
-            : Thread(false), mHardware(hw) { }
+        PreviewThread(CameraHardwareStub* hw) :
+#ifdef SINGLE_PROCESS
+            // In single process mode this thread needs to be a java thread,
+            // since we won't be calling through the binder.
+            Thread(true),
+#else
+            Thread(false),
+#endif
+              mHardware(hw) { }
         virtual void onFirstRef() {
             run("CameraPreviewThread", PRIORITY_URGENT_DISPLAY);
         }
@@ -102,18 +113,15 @@
     bool                mPreviewRunning;
     int                 mPreviewFrameSize;
 
-    shutter_callback    mShutterCallback;
-    raw_callback        mRawPictureCallback;
-    jpeg_callback       mJpegPictureCallback;
-    void                *mPictureCallbackCookie;
-
     // protected by mLock
     sp<PreviewThread>   mPreviewThread;
-    preview_callback    mPreviewCallback;
-    void                *mPreviewCallbackCookie;
 
-    autofocus_callback  mAutoFocusCallback;
-    void                *mAutoFocusCallbackCookie;
+    notify_callback    mNotifyCb;
+    data_callback      mDataCb;
+    data_callback_timestamp mDataCbTimestamp;
+    void               *mCallbackCookie;
+
+    int32_t             mMsgEnabled;
 
     // only used from PreviewThread
     int                 mCurrentPreviewFrame;
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index e7c1fbb..e66b00f 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -59,6 +59,7 @@
 #define DEBUG_DUMP_PREVIEW_FRAME_TO_FILE 0 /* n-th frame to write */
 #define DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE 0
 #define DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE 0
+#define DEBUG_DUMP_POSTVIEW_SNAPSHOT_TO_FILE 0
 
 #if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
 static int debug_frame_cnt;
@@ -218,6 +219,16 @@
     mHardware = openCameraHardware();
     mUseOverlay = mHardware->useOverlay();
 
+    mHardware->setCallbacks(notifyCallback,
+                            dataCallback,
+                            dataCallbackTimestamp,
+                            mCameraService.get());
+
+    // Enable zoom, error, and focus messages by default
+    mHardware->enableMsgType(CAMERA_MSG_ERROR |
+                             CAMERA_MSG_ZOOM |
+                             CAMERA_MSG_FOCUS);
+
     mMediaPlayerClick = newMediaPlayer("/system/media/audio/ui/camera_click.ogg");
     mMediaPlayerBeep = newMediaPlayer("/system/media/audio/ui/VideoRecord.ogg");
     mOverlayW = 0;
@@ -391,7 +402,13 @@
     // idle state.
     mHardware->stopPreview();
     // Cancel all picture callbacks.
-    mHardware->cancelPicture(true, true, true);
+    mHardware->disableMsgType(CAMERA_MSG_SHUTTER |
+                              CAMERA_MSG_POSTVIEW_FRAME |
+                              CAMERA_MSG_RAW_IMAGE |
+                              CAMERA_MSG_COMPRESSED_IMAGE);
+    mHardware->cancelPicture();
+    // Turn off remaining messages.
+    mHardware->disableMsgType(CAMERA_MSG_ALL_MSGS);
     // Release the hardware resources.
     mHardware->release();
     // Release the held overlay resources.
@@ -456,6 +473,13 @@
     Mutex::Autolock lock(mLock);
     if (checkPid() != NO_ERROR) return;
     mPreviewCallbackFlag = callback_flag;
+
+    if(mUseOverlay) {
+        if(mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK)
+            mHardware->enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+        else
+            mHardware->disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+    }
 }
 
 // start preview mode
@@ -514,7 +538,7 @@
     }
 
     // start recording mode
-    ret = mHardware->startRecording(recordingCallback, mCameraService.get());
+    ret = mHardware->startRecording();
     if (ret != NO_ERROR) {
         LOGE("mHardware->startRecording() failed with status %d", ret);
     }
@@ -617,10 +641,10 @@
             ret = setOverlay();
         }
         if (ret != NO_ERROR) return ret;
-        ret = mHardware->startPreview(NULL, mCameraService.get());
+        ret = mHardware->startPreview();
     } else {
-        ret = mHardware->startPreview(previewCallback,
-                                      mCameraService.get());
+        mHardware->enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+        ret = mHardware->startPreview();
         if (ret != NO_ERROR) return ret;
         // If preview display has been set, register preview buffers now.
         if (mSurface != 0) {
@@ -647,6 +671,9 @@
         mMediaPlayerBeep->seekTo(0);
         mMediaPlayerBeep->start();
     }
+
+    mHardware->enableMsgType(CAMERA_MSG_VIDEO_FRAME);
+
     return startCameraMode(CAMERA_RECORDING_MODE);
 }
 
@@ -664,6 +691,7 @@
     }
 
     mHardware->stopPreview();
+    mHardware->disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
     LOGD("stopPreview(), hardware stopped OK");
 
     if (mSurface != 0 && !mUseOverlay) {
@@ -689,8 +717,11 @@
         mMediaPlayerBeep->seekTo(0);
         mMediaPlayerBeep->start();
     }
+
     mHardware->stopRecording();
+    mHardware->disableMsgType(CAMERA_MSG_VIDEO_FRAME);
     LOGD("stopRecording(), hardware stopped OK");
+
     mPreviewBuffer.clear();
 }
 
@@ -778,65 +809,6 @@
 }
 #endif
 
-// preview callback - frame buffer update
-void CameraService::Client::previewCallback(const sp<IMemory>& mem, void* user)
-{
-    LOGV("previewCallback()");
-    sp<Client> client = getClientFromCookie(user);
-    if (client == 0) {
-        return;
-    }
-
-#if DEBUG_HEAP_LEAKS && 0 // debugging
-    if (gWeakHeap == NULL) {
-        ssize_t offset;
-        size_t size;
-        sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
-        if (gWeakHeap != heap) {
-            LOGD("SETTING PREVIEW HEAP");
-            heap->trackMe(true, true);
-            gWeakHeap = heap;
-        }
-    }
-#endif
-
-#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
-    {
-        if (debug_frame_cnt++ == DEBUG_DUMP_PREVIEW_FRAME_TO_FILE) {
-            ssize_t offset;
-            size_t size;
-            sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
-            dump_to_file("/data/preview.yuv",
-                         (uint8_t *)heap->base() + offset, size);
-        }
-    }
-#endif
-
-    // The strong pointer guarantees the client will exist, but no lock is held.
-    client->postPreviewFrame(mem);
-
-#if DEBUG_CLIENT_REFERENCES
-    //**** if the client's refcount is 1, then we are about to destroy it here,
-    // which is bad--print all refcounts.
-    if (client->getStrongCount() == 1) {
-        LOGE("++++++++++++++++ (PREVIEW) THIS WILL CAUSE A LOCKUP!");
-        client->printRefs();
-    }
-#endif
-}
-
-// recording callback
-void CameraService::Client::recordingCallback(nsecs_t timestamp, const sp<IMemory>& mem, void* user)
-{
-    LOGV("recordingCallback");
-    sp<Client> client = getClientFromCookie(user);
-    if (client == 0) {
-        return;
-    }
-    // The strong pointer guarantees the client will exist, but no lock is held.
-    client->postRecordingFrame(timestamp, mem);
-}
-
 // take a picture - image is returned in callback
 status_t CameraService::Client::autoFocus()
 {
@@ -851,8 +823,7 @@
         return INVALID_OPERATION;
     }
 
-    return mHardware->autoFocus(autoFocusCallback,
-                                mCameraService.get());
+    return mHardware->autoFocus();
 }
 
 // take a picture - image is returned in callback
@@ -869,38 +840,36 @@
         return INVALID_OPERATION;
     }
 
-    return mHardware->takePicture(shutterCallback,
-                                  yuvPictureCallback,
-                                  jpegPictureCallback,
-                                  mCameraService.get());
+    mHardware->enableMsgType(CAMERA_MSG_SHUTTER |
+                             CAMERA_MSG_POSTVIEW_FRAME |
+                             CAMERA_MSG_RAW_IMAGE |
+                             CAMERA_MSG_COMPRESSED_IMAGE);
+
+    return mHardware->takePicture();
 }
 
-// picture callback - snapshot taken
-void CameraService::Client::shutterCallback(void *user)
+// snapshot taken
+void CameraService::Client::handleShutter()
 {
-    sp<Client> client = getClientFromCookie(user);
-    if (client == 0) {
-        return;
-    }
-
     // Play shutter sound.
-    if (client->mMediaPlayerClick.get() != NULL) {
-        client->mMediaPlayerClick->seekTo(0);
-        client->mMediaPlayerClick->start();
+    if (mMediaPlayerClick.get() != NULL) {
+        mMediaPlayerClick->seekTo(0);
+        mMediaPlayerClick->start();
     }
 
     // Screen goes black after the buffer is unregistered.
-    if (client->mSurface != 0 && !client->mUseOverlay) {
-        client->mSurface->unregisterBuffers();
+    if (mSurface != 0 && !mUseOverlay) {
+        mSurface->unregisterBuffers();
     }
 
-    client->postShutter();
+    mCameraClient->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
+    mHardware->disableMsgType(CAMERA_MSG_SHUTTER);
 
     // It takes some time before yuvPicture callback to be called.
     // Register the buffer for raw image here to reduce latency.
-    if (client->mSurface != 0 && !client->mUseOverlay) {
+    if (mSurface != 0 && !mUseOverlay) {
         int w, h;
-        CameraParameters params(client->mHardware->getParameters());
+        CameraParameters params(mHardware->getParameters());
         params.getPictureSize(&w, &h);
         uint32_t transform = 0;
         if (params.getOrientation() == CameraParameters::CAMERA_ORIENTATION_PORTRAIT) {
@@ -908,26 +877,92 @@
             transform = ISurface::BufferHeap::ROT_90;
         }
         ISurface::BufferHeap buffers(w, h, w, h,
-            PIXEL_FORMAT_YCbCr_420_SP, transform, 0, client->mHardware->getRawHeap());
+            PIXEL_FORMAT_YCbCr_420_SP, transform, 0, mHardware->getRawHeap());
 
-        client->mSurface->registerBuffers(buffers);
+        mSurface->registerBuffers(buffers);
     }
 }
 
-// picture callback - raw image ready
-void CameraService::Client::yuvPictureCallback(const sp<IMemory>& mem,
-                                               void *user)
+// preview callback - frame buffer update
+void CameraService::Client::handlePreviewData(const sp<IMemory>& mem)
 {
-    sp<Client> client = getClientFromCookie(user);
-    if (client == 0) {
-        return;
+    ssize_t offset;
+    size_t size;
+    sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
+
+#if DEBUG_HEAP_LEAKS && 0 // debugging
+    if (gWeakHeap == NULL) {
+        if (gWeakHeap != heap) {
+            LOGD("SETTING PREVIEW HEAP");
+            heap->trackMe(true, true);
+            gWeakHeap = heap;
+        }
     }
-    if (mem == NULL) {
-        client->postRaw(NULL);
-        client->postError(UNKNOWN_ERROR);
+#endif
+#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
+    {
+        if (debug_frame_cnt++ == DEBUG_DUMP_PREVIEW_FRAME_TO_FILE) {
+            dump_to_file("/data/preview.yuv",
+                         (uint8_t *)heap->base() + offset, size);
+        }
+    }
+#endif
+
+    if (!mUseOverlay)
+    {
+        Mutex::Autolock surfaceLock(mSurfaceLock);
+        if (mSurface != NULL) {
+            mSurface->postBuffer(offset);
+        }
+    }
+
+    // Is the callback enabled or not?
+    if (!(mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
+        // If the enable bit is off, the copy-out and one-shot bits are ignored
+        LOGV("frame callback is diabled");
         return;
     }
 
+    // Is the received frame copied out or not?
+    if (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
+        LOGV("frame is copied out");
+        copyFrameAndPostCopiedFrame(heap, offset, size);
+    } else {
+        LOGV("frame is directly sent out without copying");
+        mCameraClient->dataCallback(CAMERA_MSG_PREVIEW_FRAME, mem);
+    }
+
+    // Is this is one-shot only?
+    if (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) {
+        LOGV("One-shot only, thus clear the bits and disable frame callback");
+        mPreviewCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
+                                FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
+                                FRAME_CALLBACK_FLAG_ENABLE_MASK);
+        if (mUseOverlay)
+            mHardware->disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+    }
+}
+
+// picture callback - postview image ready
+void CameraService::Client::handlePostview(const sp<IMemory>& mem)
+{
+#if DEBUG_DUMP_POSTVIEW_SNAPSHOT_TO_FILE // for testing pursposes only
+    {
+        ssize_t offset;
+        size_t size;
+        sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
+        dump_to_file("/data/postview.yuv",
+                     (uint8_t *)heap->base() + offset, size);
+    }
+#endif
+
+    mCameraClient->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem);
+    mHardware->disableMsgType(CAMERA_MSG_POSTVIEW_FRAME);
+}
+
+// picture callback - raw image ready
+void CameraService::Client::handleRawPicture(const sp<IMemory>& mem)
+{
     ssize_t offset;
     size_t size;
     sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
@@ -935,44 +970,24 @@
     gWeakHeap = heap; // debugging
 #endif
 
-    //LOGV("yuvPictureCallback(%d, %d, %p)", offset, size, user);
+    //LOGV("handleRawPicture(%d, %d)", offset, size);
 #if DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE // for testing pursposes only
     dump_to_file("/data/photo.yuv",
                  (uint8_t *)heap->base() + offset, size);
 #endif
 
     // Put the YUV version of the snapshot in the preview display.
-    if (client->mSurface != 0 && !client->mUseOverlay) {
-        client->mSurface->postBuffer(offset);
+    if (mSurface != 0 && !mUseOverlay) {
+        mSurface->postBuffer(offset);
     }
 
-    client->postRaw(mem);
-
-#if DEBUG_CLIENT_REFERENCES
-    //**** if the client's refcount is 1, then we are about to destroy it here,
-    // which is bad--print all refcounts.
-    if (client->getStrongCount() == 1) {
-        LOGE("++++++++++++++++ (RAW) THIS WILL CAUSE A LOCKUP!");
-        client->printRefs();
-    }
-#endif
+    mCameraClient->dataCallback(CAMERA_MSG_RAW_IMAGE, mem);
+    mHardware->disableMsgType(CAMERA_MSG_RAW_IMAGE);
 }
 
-// picture callback - jpeg ready
-void CameraService::Client::jpegPictureCallback(const sp<IMemory>& mem, void *user)
+// picture callback - compressed picture ready
+void CameraService::Client::handleCompressedPicture(const sp<IMemory>& mem)
 {
-    sp<Client> client = getClientFromCookie(user);
-    if (client == 0) {
-        return;
-    }
-    if (mem == NULL) {
-        client->postJpeg(NULL);
-        client->postError(UNKNOWN_ERROR);
-        return;
-    }
-
-    /** We absolutely CANNOT call into user code with a lock held **/
-
 #if DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE // for testing pursposes only
     {
         ssize_t offset;
@@ -983,32 +998,100 @@
     }
 #endif
 
-    client->postJpeg(mem);
-
-#if DEBUG_CLIENT_REFERENCES
-    //**** if the client's refcount is 1, then we are about to destroy it here,
-    // which is bad--print all refcounts.
-    if (client->getStrongCount() == 1) {
-        LOGE("++++++++++++++++ (JPEG) THIS WILL CAUSE A LOCKUP!");
-        client->printRefs();
-    }
-#endif
+    mCameraClient->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem);
+    mHardware->disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
 }
 
-void CameraService::Client::autoFocusCallback(bool focused, void *user)
+void CameraService::Client::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2, void* user)
 {
-    LOGV("autoFocusCallback");
+    LOGV("notifyCallback(%d)", msgType);
 
     sp<Client> client = getClientFromCookie(user);
     if (client == 0) {
         return;
     }
 
-    client->postAutoFocus(focused);
+    switch (msgType) {
+        case CAMERA_MSG_SHUTTER:
+            client->handleShutter();
+            break;
+        default:
+            client->mCameraClient->notifyCallback(msgType, ext1, ext2);
+            break;
+    }
 
 #if DEBUG_CLIENT_REFERENCES
     if (client->getStrongCount() == 1) {
-        LOGE("++++++++++++++++ (AUTOFOCUS) THIS WILL CAUSE A LOCKUP!");
+        LOGE("++++++++++++++++ (NOTIFY CALLBACK) THIS WILL CAUSE A LOCKUP!");
+        client->printRefs();
+    }
+#endif
+}
+
+void CameraService::Client::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, void* user)
+{
+    LOGV("dataCallback(%d)", msgType);
+
+    sp<Client> client = getClientFromCookie(user);
+    if (client == 0) {
+        return;
+    }
+
+    if (dataPtr == NULL) {
+        LOGE("Null data returned in data callback");
+        client->mCameraClient->notifyCallback(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
+        client->mCameraClient->dataCallback(msgType, NULL);
+        return;
+    }
+
+    switch (msgType) {
+        case CAMERA_MSG_PREVIEW_FRAME:
+            client->handlePreviewData(dataPtr);
+            break;
+        case CAMERA_MSG_POSTVIEW_FRAME:
+            client->handlePostview(dataPtr);
+            break;
+        case CAMERA_MSG_RAW_IMAGE:
+            client->handleRawPicture(dataPtr);
+            break;
+        case CAMERA_MSG_COMPRESSED_IMAGE:
+            client->handleCompressedPicture(dataPtr);
+            break;
+        default:
+            client->mCameraClient->dataCallback(msgType, dataPtr);
+            break;
+    }
+
+#if DEBUG_CLIENT_REFERENCES
+    if (client->getStrongCount() == 1) {
+        LOGE("++++++++++++++++ (DATA CALLBACK) THIS WILL CAUSE A LOCKUP!");
+        client->printRefs();
+    }
+#endif
+}
+
+void CameraService::Client::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
+                                                  const sp<IMemory>& dataPtr, void* user)
+{
+    LOGV("dataCallbackTimestamp(%d)", msgType);
+
+    sp<Client> client = getClientFromCookie(user);
+    if (client == 0) {
+        return;
+    }
+
+    if (dataPtr == NULL) {
+        LOGE("Null data returned in data with timestamp callback");
+        client->mCameraClient->notifyCallback(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
+        client->mCameraClient->dataCallbackTimestamp(0, msgType, NULL);
+        return;
+    }
+
+    client->mCameraClient->dataCallbackTimestamp(timestamp, msgType, dataPtr);
+
+#if DEBUG_CLIENT_REFERENCES
+    if (client->getStrongCount() == 1) {
+        LOGE("++++++++++++++++ (DATA CALLBACK TIMESTAMP) THIS WILL CAUSE A LOCKUP!");
         client->printRefs();
     }
 #endif
@@ -1048,30 +1131,6 @@
     return params;
 }
 
-void CameraService::Client::postAutoFocus(bool focused)
-{
-    LOGV("postAutoFocus");
-    mCameraClient->notifyCallback(CAMERA_MSG_FOCUS, (int32_t)focused, 0);
-}
-
-void CameraService::Client::postShutter()
-{
-    LOGD("postShutter");
-    mCameraClient->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
-}
-
-void CameraService::Client::postRaw(const sp<IMemory>& mem)
-{
-    LOGD("postRaw");
-    mCameraClient->dataCallback(CAMERA_MSG_RAW_IMAGE, mem);
-}
-
-void CameraService::Client::postJpeg(const sp<IMemory>& mem)
-{
-    LOGD("postJpeg");
-    mCameraClient->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem);
-}
-
 void CameraService::Client::copyFrameAndPostCopiedFrame(sp<IMemoryHeap> heap, size_t offset, size_t size)
 {
     LOGV("copyFrameAndPostCopiedFrame");
@@ -1100,65 +1159,6 @@
     mCameraClient->dataCallback(CAMERA_MSG_PREVIEW_FRAME, frame);
 }
 
-void CameraService::Client::postRecordingFrame(nsecs_t timestamp, const sp<IMemory>& frame)
-{
-    LOGV("postRecordingFrame");
-    if (frame == 0) {
-        LOGW("frame is a null pointer");
-        return;
-    }
-    mCameraClient->dataCallbackTimestamp(timestamp, CAMERA_MSG_VIDEO_FRAME, frame);
-}
-
-void CameraService::Client::postPreviewFrame(const sp<IMemory>& mem)
-{
-    LOGV("postPreviewFrame");
-    if (mem == 0) {
-        LOGW("mem is a null pointer");
-        return;
-    }
-
-    ssize_t offset;
-    size_t size;
-    sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
-    if ( !mUseOverlay )
-    {
-        Mutex::Autolock surfaceLock(mSurfaceLock);
-        if (mSurface != NULL) {
-            mSurface->postBuffer(offset);
-        }
-    }
-
-    // Is the callback enabled or not?
-    if (!(mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
-        // If the enable bit is off, the copy-out and one-shot bits are ignored
-        LOGV("frame callback is diabled");
-        return;
-    }
-
-    // Is the received frame copied out or not?
-    if (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
-        LOGV("frame is copied out");
-        copyFrameAndPostCopiedFrame(heap, offset, size);
-    } else {
-        LOGV("frame is directly sent out without copying");
-        mCameraClient->dataCallback(CAMERA_MSG_PREVIEW_FRAME, mem);
-    }
-
-    // Is this is one-shot only?
-    if (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) {
-        LOGV("One-shot only, thus clear the bits and disable frame callback");
-        mPreviewCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
-                                FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
-                                FRAME_CALLBACK_FLAG_ENABLE_MASK);
-    }
-}
-
-void CameraService::Client::postError(status_t error)
-{
-    mCameraClient->notifyCallback(CAMERA_MSG_ERROR, error, 0);
-}
-
 status_t CameraService::dump(int fd, const Vector<String16>& args)
 {
     const size_t SIZE = 256;
diff --git a/camera/libcameraservice/CameraService.h b/camera/libcameraservice/CameraService.h
index 8a49fa6..f8c7216 100644
--- a/camera/libcameraservice/CameraService.h
+++ b/camera/libcameraservice/CameraService.h
@@ -132,22 +132,20 @@
 
                     status_t    checkPid();
 
-        static      void        recordingCallback(nsecs_t timestamp, const sp<IMemory>& mem, void* user);
-        static      void        previewCallback(const sp<IMemory>& mem, void* user);
-        static      void        shutterCallback(void *user);
-        static      void        yuvPictureCallback(const sp<IMemory>& mem, void* user);
-        static      void        jpegPictureCallback(const sp<IMemory>& mem, void* user);
-        static      void        autoFocusCallback(bool focused, void* user);
+        static      void        notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2, void* user);
+        static      void        dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, void* user);
+        static      void        dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
+                                                      const sp<IMemory>& dataPtr, void* user);
+
         static      sp<Client>  getClientFromCookie(void* user);
 
-                    void        postShutter();
-                    void        postRaw(const sp<IMemory>& mem);
-                    void        postJpeg(const sp<IMemory>& mem);
-                    void        postPreviewFrame(const sp<IMemory>& mem);
-                    void        postRecordingFrame(nsecs_t timestamp, const sp<IMemory>& frame);
+                    void        handlePreviewData(const sp<IMemory>&);
+                    void        handleShutter();
+                    void        handlePostview(const sp<IMemory>&);
+                    void        handleRawPicture(const sp<IMemory>&);
+                    void        handleCompressedPicture(const sp<IMemory>&);
+
                     void        copyFrameAndPostCopiedFrame(sp<IMemoryHeap> heap, size_t offset, size_t size);
-                    void        postError(status_t error);
-                    void        postAutoFocus(bool focused);
 
         // camera operation mode
         enum camera_mode {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 32a2891..e045105 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1701,6 +1701,14 @@
             printRow(pw, TWO_COUNT_COLUMNS, "numPagers:", stats.numPagers, "inactivePageKB:",
                     (stats.totalBytes - stats.referencedBytes) / 1024);
             printRow(pw, ONE_COUNT_COLUMN, "activePageKB:", stats.referencedBytes / 1024);
+            
+            // Asset details.
+            String assetAlloc = AssetManager.getAssetAllocations();
+            if (assetAlloc != null) {
+                pw.println(" ");
+                pw.println(" Asset Allocations");
+                pw.print(assetAlloc);
+            }
         }
 
         private void printRow(PrintWriter pw, String format, Object...objs) {
diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java
index 7e71088..a74fbe4 100644
--- a/core/java/android/app/ApplicationContext.java
+++ b/core/java/android/app/ApplicationContext.java
@@ -1664,6 +1664,15 @@
         }
 
         @Override
+        public int checkSignatures(int uid1, int uid2) {
+            try {
+                return mPM.checkUidSignatures(uid1, uid2);
+            } catch (RemoteException e) {
+                throw new RuntimeException("Package manager has died", e);
+            }
+        }
+
+        @Override
         public String[] getPackagesForUid(int uid) {
             try {
                 return mPM.getPackagesForUid(uid);
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index 7ad6423..97d46f8 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -369,7 +369,26 @@
  * forget to decode it.  (See {@link android.net.Uri#getPathSegments} and
  * {@link android.net.Uri#getLastPathSegment} for helpful utilities you can use here.)</li>
  * </ul>
- * 
+ *
+ * <p><b>Providing access to Content Providers that require permissions.</b>  If your content
+ * provider declares an android:readPermission in your application's manifest, you must provide
+ * access to the search infrastructure to the search suggestion path by including a path-permission
+ * that grants android:readPermission access to "android.permission.GLOBAL_SEARCH".  Granting access
+ * explicitly to the search infrastructure ensures it will be able to access the search suggestions
+ * without needing to know ahead of time any other details of the permissions protecting your
+ * provider.  Content providers that require no permissions are already available to the search
+ * infrastructure.  Here is an example of a provider that protects access to it with permissions,
+ * and provides read access to the search infrastructure to the path that it expects to receive the
+ * suggestion query on:
+ * <pre class="prettyprint">
+ * &lt;provider android:name="MyProvider" android:authorities="myprovider"
+ *        android:readPermission="android.permission.READ_MY_DATA"
+ *        android:writePermission="android.permission.WRITE_MY_DATA"&gt;
+ *    &lt;path-permission android:path="/search_suggest_query"
+ *            android:readPermission="android.permission.GLOBAL_SEARCH" /&gt;
+ * &lt;/provider&gt;
+ * </pre>
+ *
  * <p><b>Handling empty queries.</b>  Your application should handle the "empty query"
  * (no user text entered) case properly, and generate useful suggestions in this case.  There are a
  * number of ways to do this;  Two are outlined here:
@@ -377,7 +396,7 @@
  * unfiltered.  (example: People)</li>
  * <li>For a query search, you could simply present the most recent queries.  This allows the user
  * to quickly repeat a recent search.</li></ul>
- * 
+ *
  * <p><b>The Format of Individual Suggestions.</b>  Your suggestions are communicated back to the
  * Search Manager by way of a {@link android.database.Cursor Cursor}.  The Search Manager will
  * usually pass a null Projection, which means that your provider can simply return all appropriate
@@ -453,13 +472,42 @@
  *         <td align="center">No</td>
  *     </tr>
  *     
+ *     <tr><th>{@link #SUGGEST_COLUMN_INTENT_EXTRA_DATA}</th>
+ *         <td>If this column exists <i>and</i> this element exists at a given row, this is the
+ *             data that will be used when forming the suggestion's intent.  If not provided,
+ *             the Intent's extra data field will be null.  This column allows suggestions to
+ *             provide additional arbitrary data which will be included as an extra under the
+ *             key {@link #EXTRA_DATA_KEY}.</td>
+ *         <td align="center">No.</td>
+ *     </tr>
+ *
  *     <tr><th>{@link #SUGGEST_COLUMN_QUERY}</th>
  *         <td>If this column exists <i>and</i> this element exists at the given row, this is the 
  *             data that will be used when forming the suggestion's query.</td>
  *         <td align="center">Required if suggestion's action is 
  *             {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH}, optional otherwise.</td>
  *     </tr>
- *     
+ *
+ *     <tr><th>{@link #SUGGEST_COLUMN_SHORTCUT_ID}</th>
+ *         <td>This column is used to indicate whether a search suggestion should be stored as a
+ *             shortcut, and whether it should be validated.  Shortcuts are usually formed when the
+ *             user clicks a suggestion from Quick Search Box.  If missing, the result will be
+ *             stored as a shortcut and never refreshed.  If set to
+ *             {@link #SUGGEST_NEVER_MAKE_SHORTCUT}, the result will not be stored as a shortcut.
+ *             Otherwise, the shortcut id will be used to check back for for an up to date
+ *             suggestion using {@link #SUGGEST_URI_PATH_SHORTCUT}. Read more about shortcut
+ *             refreshing in the section about
+ *             <a href="#ExposingSearchSuggestionsToQuickSearchBox">exposing search suggestions to
+ *             Quick Search Box</a>.</td>
+ *         <td align="center">No.  Only applicable to sources included in Quick Search Box.</td>
+ *     </tr>
+ *
+ *     <tr><th>{@link #SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING}</th>
+ *         <td>This column is used to specify that a spinner should be shown in lieu of an icon2
+ *             while the shortcut of this suggestion is being refreshed.</td>
+ *         <td align="center">No.  Only applicable to sources included in Quick Search Box.</td>
+ *     </tr>
+ * 
  *     <tr><th><i>Other Columns</i></th>
  *         <td>Finally, if you have defined any <a href="#ActionKeys">Action Keys</a> and you wish 
  *             for them to have suggestion-specific definitions, you'll need to define one 
@@ -536,7 +584,55 @@
  * <a name="ExposingSearchSuggestionsToQuickSearchBox"></a>
  * <h3>Exposing Search Suggestions to Quick Search Box</h3>
  * 
- * <p>
+ * <p>Once your application is setup to provide search suggestions, making them available to the
+ * globally accessable Quick Search Box is as easy as setting android:includeInGlobalSearch to
+ * "true" in your searchable metadata file.  Beyond that, here are some more details of how
+ * suggestions interact with Quick Search Box, and optional ways that you may customize suggestions
+ * for your application.
+ *
+ * <p><b>Source Ranking:</b>  Once your application's search results are made available to Quick
+ * Search Box, how they surface to the user for a particular query will depend on how many
+ * other apps have results for that query, and how often the user has clicked on your results
+ * compared to the other apps'.  The apps with the best track record within Quick Search
+ * Box will get queried earlier and have a better chance of showing their results in the top few
+ * slots.  If there are more results than can be displayed to the user within a screen or two, the
+ * results may spill into a "more results" section that groups the remaining results by
+ * source.  The newest apps with little usage information are given middle of the road positioning
+ * until enough usage information is available to rank it as usual.  The exact formula for ranking
+ * the results is not set in stone, but suffice it is to say that providing quality results will
+ * increase the likelihood that your app's suggestions are provided in a prominent position, and
+ * apps that provide lower quality suggestions will be more likely to be pushed into the spillover
+ * area.
+ *
+ * <p><b>Search Settings:</b>  Each app that is available to Quick Search Box has an entry in the
+ * system settings where the user can enable or disable the inclusion of its results.  Below the
+ * name of the application, each application may provide a brief description of what kind of
+ * information will be made available via a search settings description string pointed to by the
+ * android:searchSettingsDescription attribute in the searchable metadata.
+ *
+ * <p><b>Shortcuts:</b>  Suggestions that are clicked on by the user are automatically made into
+ * shortcuts, or, copied so they can quickly be displayed to the user before querying any of
+ * the sources. Thereafter, the shortcutted suggestion will be displayed for the query that yielded
+ * the suggestion and for any prefixes of that query.  When multiple shortcuts are made available
+ * for a given query, they are ranked based on recency and the number of clicks they have received.
+ * You can control how your suggestions are made into shortcuts, and whether they are refreshed,
+ * using the {@link #SUGGEST_COLUMN_SHORTCUT_ID} column:
+ * <ul><li>Suggestions that do not include a shortcut id column will be made into shortcuts and
+ * never refreshed.  This makes sense for suggestions that refer to data that will never be changed
+ * or removed.</li>
+ * <li>Suggestions that include a shortcut id will be re-queried for a fresh version of the
+ * suggestion each time the shortcut is displayed.  The shortcut will be quickly displayed with
+ * whatever data was most recently available until the refresh query returns, after which the
+ * suggestion will be dynamically refreshed with the up to date information.  The shortcut refresh
+ * query will be sent to your suggestion provider with a uri of {@link #SUGGEST_URI_PATH_SHORTCUT}.
+ * The result should contain one suggestion using the same columns as the suggestion query, or be
+ * empty, indicating that the shortcut is no longer valid.  Shortcut ids make sense when referring
+ * to data that may change over time, such as a contact's presence status.  If a suggestion refers
+ * to data that could take longer to refresh, such as a network based refresh of a stock quote, you
+ * may include {@link #SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING} to show a progress spinner for the
+ * right hand icon until the refresh is complete.</li>
+ * <li>Finally, to prevent a suggestion from being copied into a shortcut, you may provide a
+ * shortcut id with a value of {@link #SUGGEST_NEVER_MAKE_SHORTCUT}.</li></ul>
  * 
  * <a name="ActionKeys"></a>
  * <h3>Action Keys</h3>
@@ -673,7 +769,7 @@
  *             entered.</td>
  *         <td align="center">No</td>
  *     </tr>
- *     
+ *
  *     <tr><th>android:searchButtonText</th>
  *         <td>If provided, this text will replace the default text in the "Search" button.</td>
  *         <td align="center">No</td>
@@ -853,7 +949,48 @@
  *     
  *     </tbody>
  * </table>
- * 
+ *
+ * <p>Elements of search metadata that configure search suggestions being available to Quick Search
+ * Box:
+ * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
+ *
+ *     <thead>
+ *     <tr><th>Attribute</th> <th>Description</th> <th>Required?</th></tr>
+ *     </thead>
+ *
+ *     <tr><th>android:includeInGlobalSearch</th>
+ *         <td>If true, indicates the search suggestions provided by your application should be
+ *             included in the globally accessible Quick Search Box.  The attributes below are only
+ *             applicable if this is set to true.</td>
+ *         <td align="center">Yes</td>
+ *     </tr>
+ *
+ *     <tr><th>android:searchSettingsDescription</th>
+ *         <td>If provided, provides a brief description of the search suggestions that are provided
+ *             by your application to Quick Search Box, and will be displayed in the search settings
+ *             entry for your application.</td>
+ *         <td align="center">No</td>
+ *     </tr>
+ *
+ *     <tr><th>android:queryAfterZeroResults</th>
+ *         <td>Indicates whether a source should be invoked for supersets of queries it has
+ *             returned zero results for in the past.  For example, if a source returned zero
+ *             results for "bo", it would be ignored for "bob".  If set to false, this source
+ *             will only be ignored for a single session; the next time the search dialog is
+ *             invoked, all sources will be queried.  The default value is false.</td>
+ *         <td align="center">No</td>
+ *     </tr>
+ *
+ *     <tr><th>android:searchSuggestThreshold</th>
+ *         <td>Indicates the minimum number of characters needed to trigger a source from Quick
+ *             Search Box.  Only guarantees that a source will not be queried for anything shorter
+ *             than the threshold.  The default value is 0.</td>
+ *         <td align="center">No</td>
+ *     </tr>
+ *
+ *     </tbody>
+ * </table>
+ *
  * <p><b>Additional metadata for search action keys.</b>  For each action key that you would like to
  * define, you'll need to add an additional element defining that key, and using the attributes
  * discussed in <a href="#ActionKeys">Action Keys</a>.  A simple example is shown here:
@@ -1376,10 +1513,10 @@
 
     /**
      * Column name for suggestions cursor. <i>Optional.</i>  This column is used to indicate whether
-     * a search suggestion should be stored as a shortcut, and whether it should be validated.  If
+     * a search suggestion should be stored as a shortcut, and whether it should be refreshed.  If
      * missing, the result will be stored as a shortcut and never validated.  If set to
      * {@link #SUGGEST_NEVER_MAKE_SHORTCUT}, the result will not be stored as a shortcut.
-     * Otherwise, the shortcut id will be used to check back for validation via
+     * Otherwise, the shortcut id will be used to check back for an up to date suggestion using
      * {@link #SUGGEST_URI_PATH_SHORTCUT}.
      */
     public final static String SUGGEST_COLUMN_SHORTCUT_ID = "suggest_shortcut_id";
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 78b6cf1..fd8776f 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -335,6 +335,25 @@
     }
     
     /**
+     * Clear the offsets previously associated with this window through
+     * {@link #setWallpaperOffsets(IBinder, float, float)}.  This reverts
+     * the window to its default state, where it does not cause the wallpaper
+     * to scroll from whatever its last offsets were.
+     * 
+     * @param windowToken The window who these offsets should be associated
+     * with, as returned by {@link android.view.View#getWindowVisibility()
+     * View.getWindowToken()}.
+     */
+    public void clearWallpaperOffsets(IBinder windowToken) {
+        try {
+            ViewRoot.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
+                    windowToken, -1, -1);
+        } catch (RemoteException e) {
+            // Ignore.
+        }
+    }
+    
+    /**
      * Remove any currently set wallpaper, reverting to the system's default
      * wallpaper. On success, the intent {@link Intent#ACTION_WALLPAPER_CHANGED}
      * is broadcast.
diff --git a/core/java/android/content/AsyncQueryHandler.java b/core/java/android/content/AsyncQueryHandler.java
index c5606ac..5e88de0 100644
--- a/core/java/android/content/AsyncQueryHandler.java
+++ b/core/java/android/content/AsyncQueryHandler.java
@@ -38,7 +38,8 @@
     private static final int EVENT_ARG_INSERT = 2;
     private static final int EVENT_ARG_UPDATE = 3;
     private static final int EVENT_ARG_DELETE = 4;
-    
+    private static final int EVENT_ARG_QUERY_ENTITIES = 5;
+
     /* package */ final WeakReference<ContentResolver> mResolver;
 
     private static Looper sLooper = null;
@@ -85,13 +86,25 @@
                             cursor.getCount();
                         }
                     } catch (Exception e) {
-                        Log.d(TAG, e.toString());
+                        Log.w(TAG, e.toString());
                         cursor = null;
                     }
 
                     args.result = cursor;
                     break;
 
+                case EVENT_ARG_QUERY_ENTITIES:
+                    EntityIterator iterator = null;
+                    try {
+                        iterator = resolver.queryEntities(args.uri, args.selection,
+                                args.selectionArgs, args.orderBy);
+                    } catch (Exception e) {
+                        Log.w(TAG, e.toString());
+                    }
+
+                    args.result = iterator;
+                    break;
+
                 case EVENT_ARG_INSERT:
                     args.result = resolver.insert(args.uri, args.values);
                     break;
@@ -104,7 +117,6 @@
                 case EVENT_ARG_DELETE:
                     args.result = resolver.delete(args.uri, args.selection, args.selectionArgs);
                     break;
-
             }
 
             // passing the original token value back to the caller
@@ -129,7 +141,7 @@
             if (sLooper == null) {
                 HandlerThread thread = new HandlerThread("AsyncQueryWorker");
                 thread.start();
-                
+
                 sLooper = thread.getLooper();
             }
         }
@@ -183,6 +195,44 @@
     }
 
     /**
+     * This method begins an asynchronous query for an {@link EntityIterator}.
+     * When the query is done {@link #onQueryEntitiesComplete} is called.
+     *
+     * @param token A token passed into {@link #onQueryComplete} to identify the
+     *            query.
+     * @param cookie An object that gets passed into {@link #onQueryComplete}
+     * @param uri The URI, using the content:// scheme, for the content to
+     *            retrieve.
+     * @param selection A filter declaring which rows to return, formatted as an
+     *            SQL WHERE clause (excluding the WHERE itself). Passing null
+     *            will return all rows for the given URI.
+     * @param selectionArgs You may include ?s in selection, which will be
+     *            replaced by the values from selectionArgs, in the order that
+     *            they appear in the selection. The values will be bound as
+     *            Strings.
+     * @param orderBy How to order the rows, formatted as an SQL ORDER BY clause
+     *            (excluding the ORDER BY itself). Passing null will use the
+     *            default sort order, which may be unordered.
+     */
+    public void startQueryEntities(int token, Object cookie, Uri uri, String selection,
+            String[] selectionArgs, String orderBy) {
+        // Use the token as what so cancelOperations works properly
+        Message msg = mWorkerThreadHandler.obtainMessage(token);
+        msg.arg1 = EVENT_ARG_QUERY_ENTITIES;
+
+        WorkerArgs args = new WorkerArgs();
+        args.handler = this;
+        args.uri = uri;
+        args.selection = selection;
+        args.selectionArgs = selectionArgs;
+        args.orderBy = orderBy;
+        args.cookie = cookie;
+        msg.obj = args;
+
+        mWorkerThreadHandler.sendMessage(msg);
+    }
+
+    /**
      * Attempts to cancel operation that has not already started. Note that
      * there is no guarantee that the operation will be canceled. They still may
      * result in a call to on[Query/Insert/Update/Delete]Complete after this
@@ -280,8 +330,8 @@
      * Called when an asynchronous query is completed.
      *
      * @param token the token to identify the query, passed in from
-     *        {@link #startQuery}.
-     * @param cookie the cookie object that's passed in from {@link #startQuery}.
+     *            {@link #startQuery}.
+     * @param cookie the cookie object passed in from {@link #startQuery}.
      * @param cursor The cursor holding the results from the query.
      */
     protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
@@ -289,6 +339,17 @@
     }
 
     /**
+     * Called when an asynchronous query is completed.
+     *
+     * @param token The token to identify the query.
+     * @param cookie The cookie object.
+     * @param iterator The iterator holding the query results.
+     */
+    protected void onQueryEntitiesComplete(int token, Object cookie, EntityIterator iterator) {
+        // Empty
+    }
+
+    /**
      * Called when an asynchronous insert is completed.
      *
      * @param token the token to identify the query, passed in from
@@ -338,13 +399,17 @@
 
         int token = msg.what;
         int event = msg.arg1;
-        
+
         // pass token back to caller on each callback.
         switch (event) {
             case EVENT_ARG_QUERY:
                 onQueryComplete(token, args.cookie, (Cursor) args.result);
                 break;
 
+            case EVENT_ARG_QUERY_ENTITIES:
+                onQueryEntitiesComplete(token, args.cookie, (EntityIterator)args.result);
+                break;
+
             case EVENT_ARG_INSERT:
                 onInsertComplete(token, args.cookie, (Uri) args.result);
                 break;
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index d9f298d..7760612 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -75,6 +75,8 @@
     
     int checkSignatures(String pkg1, String pkg2);
     
+    int checkUidSignatures(int uid1, int uid2);
+    
     String[] getPackagesForUid(int uid);
     
     String getNameForUid(int uid);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index bca1715..fca005c 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -865,6 +865,7 @@
      * {@link #SIGNATURE_SECOND_NOT_SIGNED}, {@link #SIGNATURE_NO_MATCH},
      * or {@link #SIGNATURE_UNKNOWN_PACKAGE}.
      *
+     * @see #checkSignatures(int, int)
      * @see #SIGNATURE_MATCH
      * @see #SIGNATURE_NEITHER_SIGNED
      * @see #SIGNATURE_FIRST_NOT_SIGNED
@@ -875,6 +876,34 @@
     public abstract int checkSignatures(String pkg1, String pkg2);
 
     /**
+     * Like {@link #checkSignatures(String, String)}, but takes UIDs of
+     * the two packages to be checked.  This can be useful, for example,
+     * when doing the check in an IPC, where the UID is the only identity
+     * available.  It is functionally identical to determining the package
+     * associated with the UIDs and checking their signatures.
+     *
+     * @param uid1 First UID whose signature will be compared.
+     * @param uid2 Second UID whose signature will be compared.
+     * @return Returns an integer indicating whether there is a matching
+     * signature: the value is >= 0 if there is a match (or neither package
+     * is signed), or < 0 if there is not a match.  The match result can be
+     * further distinguished with the success (>= 0) constants
+     * {@link #SIGNATURE_MATCH}, {@link #SIGNATURE_NEITHER_SIGNED}; or
+     * failure (< 0) constants {@link #SIGNATURE_FIRST_NOT_SIGNED},
+     * {@link #SIGNATURE_SECOND_NOT_SIGNED}, {@link #SIGNATURE_NO_MATCH},
+     * or {@link #SIGNATURE_UNKNOWN_PACKAGE}.
+     *
+     * @see #checkSignatures(int, int)
+     * @see #SIGNATURE_MATCH
+     * @see #SIGNATURE_NEITHER_SIGNED
+     * @see #SIGNATURE_FIRST_NOT_SIGNED
+     * @see #SIGNATURE_SECOND_NOT_SIGNED
+     * @see #SIGNATURE_NO_MATCH
+     * @see #SIGNATURE_UNKNOWN_PACKAGE
+     */
+    public abstract int checkSignatures(int uid1, int uid2);
+
+    /**
      * Retrieve the names of all packages that are associated with a particular
      * user id.  In most cases, this will be a single package name, the package
      * that has been assigned that user id.  Where there are multiple packages
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 8ebe093..0bc8a9d 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -667,6 +667,11 @@
     /**
      * {@hide}
      */
+    public native static final String getAssetAllocations();
+    
+    /**
+     * {@hide}
+     */
     public native static final int getGlobalAssetManagerCount();
     
     private native final int newTheme();
diff --git a/core/java/android/content/res/StringBlock.java b/core/java/android/content/res/StringBlock.java
index e684cb8..8fb82be 100644
--- a/core/java/android/content/res/StringBlock.java
+++ b/core/java/android/content/res/StringBlock.java
@@ -202,7 +202,7 @@
                     sub = subtag(tag, ";size=");
                     if (sub != null) {
                         int size = Integer.parseInt(sub);
-                        buffer.setSpan(new AbsoluteSizeSpan(size),
+                        buffer.setSpan(new AbsoluteSizeSpan(size, true),
                                        style[i+1], style[i+2]+1,
                                        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                     }
@@ -310,7 +310,7 @@
      * the ascent if possible, or the descent if shrinking the ascent further
      * will make the text unreadable.
      */
-    private static class Height implements LineHeightSpan {
+    private static class Height implements LineHeightSpan.WithDensity {
         private int mSize;
         private static float sProportion = 0;
 
@@ -321,9 +321,21 @@
         public void chooseHeight(CharSequence text, int start, int end,
                                  int spanstartv, int v,
                                  Paint.FontMetricsInt fm) {
-            if (fm.bottom - fm.top < mSize) {
-                fm.top = fm.bottom - mSize;
-                fm.ascent = fm.ascent - mSize;
+            // Should not get called, at least not by StaticLayout.
+            chooseHeight(text, start, end, spanstartv, v, fm, null);
+        }
+
+        public void chooseHeight(CharSequence text, int start, int end,
+                                 int spanstartv, int v,
+                                 Paint.FontMetricsInt fm, TextPaint paint) {
+            int size = mSize;
+            if (paint != null) {
+                size *= paint.density;
+            }
+
+            if (fm.bottom - fm.top < size) {
+                fm.top = fm.bottom - size;
+                fm.ascent = fm.ascent - size;
             } else {
                 if (sProportion == 0) {
                     /*
@@ -343,27 +355,27 @@
 
                 int need = (int) Math.ceil(-fm.top * sProportion);
 
-                if (mSize - fm.descent >= need) {
+                if (size - fm.descent >= need) {
                     /*
                      * It is safe to shrink the ascent this much.
                      */
 
-                    fm.top = fm.bottom - mSize;
-                    fm.ascent = fm.descent - mSize;
-                } else if (mSize >= need) {
+                    fm.top = fm.bottom - size;
+                    fm.ascent = fm.descent - size;
+                } else if (size >= need) {
                     /*
                      * We can't show all the descent, but we can at least
                      * show all the ascent.
                      */
 
                     fm.top = fm.ascent = -need;
-                    fm.bottom = fm.descent = fm.top + mSize;
+                    fm.bottom = fm.descent = fm.top + size;
                 } else {
                     /*
                      * Show as much of the ascent as we can, and no descent.
                      */
 
-                    fm.top = fm.ascent = -mSize;
+                    fm.top = fm.ascent = -size;
                     fm.bottom = fm.descent = 0;
                 }
             }
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 40d2c86..aa3b852 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -40,15 +40,16 @@
     private static final String TAG = "Camera";
     
     // These match the enums in frameworks/base/include/ui/Camera.h
-    private static final int CAMERA_MSG_ERROR = 0;
-    private static final int CAMERA_MSG_SHUTTER = 1;
-    private static final int CAMERA_MSG_FOCUS = 2;
-    private static final int CAMERA_MSG_ZOOM = 3;
-    private static final int CAMERA_MSG_PREVIEW_FRAME = 4;
-    private static final int CAMERA_MSG_VIDEO_FRAME = 5;
-    private static final int CAMERA_MSG_POSTVIEW_FRAME = 6;
-    private static final int CAMERA_MSG_RAW_IMAGE = 7;
-    private static final int CAMERA_MSG_COMPRESSED_IMAGE = 8;
+    private static final int CAMERA_MSG_ERROR            = 0x001;
+    private static final int CAMERA_MSG_SHUTTER          = 0x002;
+    private static final int CAMERA_MSG_FOCUS            = 0x004;
+    private static final int CAMERA_MSG_ZOOM             = 0x008;
+    private static final int CAMERA_MSG_PREVIEW_FRAME    = 0x010;
+    private static final int CAMERA_MSG_VIDEO_FRAME      = 0x020;
+    private static final int CAMERA_MSG_POSTVIEW_FRAME   = 0x040;
+    private static final int CAMERA_MSG_RAW_IMAGE        = 0x080;
+    private static final int CAMERA_MSG_COMPRESSED_IMAGE = 0x100;
+    private static final int CAMERA_MSG_ALL_MSGS         = 0x1FF;
 
     private int mNativeContext; // accessed by native methods
     private EventHandler mEventHandler;
diff --git a/core/java/android/inputmethodservice/Keyboard.java b/core/java/android/inputmethodservice/Keyboard.java
index fea63be..4814b0a 100755
--- a/core/java/android/inputmethodservice/Keyboard.java
+++ b/core/java/android/inputmethodservice/Keyboard.java
@@ -142,7 +142,7 @@
     private int[][] mGridNeighbors;
     private int mProximityThreshold;
     /** Number of key widths from current touch point to search for nearest keys. */
-    private static float SEARCH_DISTANCE = 1.4f;
+    private static float SEARCH_DISTANCE = 1.8f;
 
     /**
      * Container for keys in the keyboard. All keys in a row are at the same Y-coordinate. 
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 1429bc1..a127df0 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -18,6 +18,7 @@
 
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.os.Binder;
 import android.os.RemoteException;
 
 /**
@@ -114,15 +115,64 @@
     public static final String ACTION_BACKGROUND_DATA_SETTING_CHANGED =
             "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED";
 
-    public static final int TYPE_MOBILE = 0;
-    public static final int TYPE_WIFI   = 1;
+    /**
+     * The Default Mobile data connection.  When active, all data traffic
+     * will use this connection by default.  Should not coexist with other
+     * default connections.
+     */
+    public static final int TYPE_MOBILE      = 0;
+    /**
+     * The Default WIFI data connection.  When active, all data traffic
+     * will use this connection by default.  Should not coexist with other
+     * default connections.
+     */
+    public static final int TYPE_WIFI        = 1;
+    /**
+     * An MMS-specific Mobile data connection.  This connection may be the
+     * same as {@link #TYPEMOBILE} but it may be different.  This is used
+     * by applications needing to talk to the carrier's Multimedia Messaging
+     * Service servers.  It may coexist with default data connections.
+     * {@hide}
+     */
+    public static final int TYPE_MOBILE_MMS  = 2;
+    /**
+     * A SUPL-specific Mobile data connection.  This connection may be the
+     * same as {@link #TYPEMOBILE} but it may be different.  This is used
+     * by applications needing to talk to the carrier's Secure User Plane
+     * Location servers for help locating the device.  It may coexist with
+     * default data connections.
+     * {@hide}
+     */
+    public static final int TYPE_MOBILE_SUPL = 3;
+    /**
+     * A DUN-specific Mobile data connection.  This connection may be the
+     * same as {@link #TYPEMOBILE} but it may be different.  This is used
+     * by applicaitons performing a Dial Up Networking bridge so that
+     * the carrier is aware of DUN traffic.  It may coexist with default data
+     * connections.
+     * {@hide}
+     */
+    public static final int TYPE_MOBILE_DUN  = 4;
+    /**
+     * A High Priority Mobile data connection.  This connection is typically
+     * the same as {@link #TYPEMOBILE} but the routing setup is different.
+     * Only requesting processes will have access to the Mobile DNS servers
+     * and only IP's explicitly requested via {@link #requestRouteToHost}
+     * will route over this interface.
+     *{@hide}
+     */
+    public static final int TYPE_MOBILE_HIPRI = 5;
+    /** {@hide} */
+    public static final int MAX_RADIO_TYPE   = TYPE_WIFI;
+    /** {@hide} */
+    public static final int MAX_NETWORK_TYPE = TYPE_MOBILE_HIPRI;
 
     public static final int DEFAULT_NETWORK_PREFERENCE = TYPE_WIFI;
 
     private IConnectivityManager mService;
 
     static public boolean isNetworkTypeValid(int networkType) {
-        return networkType == TYPE_WIFI || networkType == TYPE_MOBILE;
+        return networkType >= 0 && networkType <= MAX_NETWORK_TYPE;
     }
 
     public void setNetworkPreference(int preference) {
@@ -195,7 +245,8 @@
      */
     public int startUsingNetworkFeature(int networkType, String feature) {
         try {
-            return mService.startUsingNetworkFeature(networkType, feature);
+            return mService.startUsingNetworkFeature(networkType, feature,
+                    new Binder());
         } catch (RemoteException e) {
             return -1;
         }
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index de68598..9f59cce 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -17,6 +17,7 @@
 package android.net;
 
 import android.net.NetworkInfo;
+import android.os.IBinder;
 
 /**
  * Interface that answers queries about, and allows changing, the
@@ -39,7 +40,8 @@
 
     boolean setRadio(int networkType, boolean turnOn);
 
-    int startUsingNetworkFeature(int networkType, in String feature);
+    int startUsingNetworkFeature(int networkType, in String feature,
+            in IBinder binder);
 
     int stopUsingNetworkFeature(int networkType, in String feature);
 
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index 1064fb6..6b00900 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -32,9 +32,6 @@
 import android.util.Log;
 import android.text.TextUtils;
 
-import java.util.List;
-import java.util.ArrayList;
-
 /**
  * Track the state of mobile data connectivity. This is done by
  * receiving broadcast intents from the Phone process whenever
@@ -45,36 +42,47 @@
 public class MobileDataStateTracker extends NetworkStateTracker {
 
     private static final String TAG = "MobileDataStateTracker";
-    private static final boolean DBG = false;
+    private static final boolean DBG = true;
 
     private Phone.DataState mMobileDataState;
     private ITelephony mPhoneService;
-    private static final String[] sDnsPropNames = {
-          "net.rmnet0.dns1",
-          "net.rmnet0.dns2",
-          "net.eth0.dns1",
-          "net.eth0.dns2",
-          "net.eth0.dns3",
-          "net.eth0.dns4",
-          "net.gprs.dns1",
-          "net.gprs.dns2"
-    };
-    private List<String> mDnsServers;
-    private String mInterfaceName;
-    private int mDefaultGatewayAddr;
-    private int mLastCallingPid = -1;
+
+    private String mApnType;
+    private boolean mEnabled;
+    private boolean mTeardownRequested;
 
     /**
      * Create a new MobileDataStateTracker
      * @param context the application context of the caller
      * @param target a message handler for getting callbacks about state changes
+     * @param netType the ConnectivityManager network type
+     * @param apnType the Phone apnType
+     * @param tag the name of this network
      */
-    public MobileDataStateTracker(Context context, Handler target) {
-        super(context, target, ConnectivityManager.TYPE_MOBILE,
-              TelephonyManager.getDefault().getNetworkType(), "MOBILE",
-              TelephonyManager.getDefault().getNetworkTypeName());
+    public MobileDataStateTracker(Context context, Handler target,
+            int netType, String apnType, String tag) {
+        super(context, target, netType,
+                TelephonyManager.getDefault().getNetworkType(), tag,
+                TelephonyManager.getDefault().getNetworkTypeName());
+        mApnType = apnType;
         mPhoneService = null;
-        mDnsServers = new ArrayList<String>();
+        mTeardownRequested = false;
+        if(netType == ConnectivityManager.TYPE_MOBILE) {
+            mEnabled = true;
+        } else {
+            mEnabled = false;
+        }
+
+        mDnsPropNames = new String[] {
+                "net.rmnet0.dns1",
+                "net.rmnet0.dns2",
+                "net.eth0.dns1",
+                "net.eth0.dns2",
+                "net.eth0.dns3",
+                "net.eth0.dns4",
+                "net.gprs.dns1",
+                "net.gprs.dns2"};
+
     }
 
     /**
@@ -93,31 +101,70 @@
             mMobileDataState = Phone.DataState.DISCONNECTED;
     }
 
-    private static Phone.DataState getMobileDataState(Intent intent) {
+    private Phone.DataState getMobileDataState(Intent intent) {
         String str = intent.getStringExtra(Phone.STATE_KEY);
-        if (str != null)
-            return Enum.valueOf(Phone.DataState.class, str);
-        else
-            return Phone.DataState.DISCONNECTED;
+        if (str != null) {
+            String apnTypeList =
+                    intent.getStringExtra(Phone.DATA_APN_TYPES_KEY);
+            if (isApnTypeIncluded(apnTypeList)) {
+                return Enum.valueOf(Phone.DataState.class, str);
+            }
+        }
+        return Phone.DataState.DISCONNECTED;
+    }
+
+    private boolean isApnTypeIncluded(String typeList) {
+        /* comma seperated list - split and check */
+        if (typeList == null)
+            return false;
+
+        String[] list = typeList.split(",");
+        for(int i=0; i< list.length; i++) {
+            if (TextUtils.equals(list[i], mApnType) ||
+                TextUtils.equals(list[i], Phone.APN_TYPE_ALL)) {
+                return true;
+            }
+        }
+        return false;
     }
 
     private class MobileDataStateReceiver extends BroadcastReceiver {
         public void onReceive(Context context, Intent intent) {
-            if (intent.getAction().equals(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) {
+            if (intent.getAction().equals(TelephonyIntents.
+                    ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) {
                 Phone.DataState state = getMobileDataState(intent);
-                String reason = intent.getStringExtra(Phone.STATE_CHANGE_REASON_KEY);
+                String reason =
+                        intent.getStringExtra(Phone.STATE_CHANGE_REASON_KEY);
                 String apnName = intent.getStringExtra(Phone.DATA_APN_KEY);
-                boolean unavailable = intent.getBooleanExtra(Phone.NETWORK_UNAVAILABLE_KEY, false);
-                if (DBG) Log.d(TAG, "Received " + intent.getAction() +
-                    " broadcast - state = " + state
-                    + ", unavailable = " + unavailable
-                    + ", reason = " + (reason == null ? "(unspecified)" : reason));
+
+                String apnTypeList =
+                        intent.getStringExtra(Phone.DATA_APN_TYPES_KEY);
+
+                boolean unavailable = intent.getBooleanExtra(
+                        Phone.NETWORK_UNAVAILABLE_KEY, false);
+                if (DBG) Log.d(TAG, mApnType + " Received "
+                        + intent.getAction() + " broadcast - state = "
+                        + state + ", unavailable = " + unavailable
+                        + ", reason = "
+                        + (reason == null ? "(unspecified)" : reason));
+
+                if ((!isApnTypeIncluded(apnTypeList)) || mEnabled == false) {
+                    if (DBG) Log.e(TAG, "  dropped - mEnabled = "+mEnabled);
+                    return;
+                }
+
+
                 mNetworkInfo.setIsAvailable(!unavailable);
                 if (mMobileDataState != state) {
                     mMobileDataState = state;
 
                     switch (state) {
                     case DISCONNECTED:
+                        if(mTeardownRequested) {
+                            mEnabled = false;
+                            mTeardownRequested = false;
+                        }
+
                         setDetailedState(DetailedState.DISCONNECTED, reason, apnName);
                         if (mInterfaceName != null) {
                             NetworkUtils.resetConnections(mInterfaceName);
@@ -136,12 +183,12 @@
                         if (mInterfaceName == null) {
                             Log.d(TAG, "CONNECTED event did not supply interface name.");
                         }
-                        setupDnsProperties();
                         setDetailedState(DetailedState.CONNECTED, reason, apnName);
                         break;
                     }
                 }
             } else if (intent.getAction().equals(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED)) {
+                mEnabled = false;
                 String reason = intent.getStringExtra(Phone.FAILURE_REASON_KEY);
                 String apnName = intent.getStringExtra(Phone.DATA_APN_KEY);
                 if (DBG) Log.d(TAG, "Received " + intent.getAction() + " broadcast" +
@@ -154,40 +201,6 @@
         }
     }
 
-    /**
-     * Make sure that route(s) exist to the carrier DNS server(s).
-     */
-    public void addPrivateRoutes() {
-        if (mInterfaceName != null) {
-            for (String addrString : mDnsServers) {
-                int addr = NetworkUtils.lookupHost(addrString);
-                if (addr != -1) {
-                    NetworkUtils.addHostRoute(mInterfaceName, addr);
-                }
-            }
-        }
-    }
-
-    public void removePrivateRoutes() {
-        if(mInterfaceName != null) {
-            NetworkUtils.removeHostRoutes(mInterfaceName);
-        }
-    }
-
-    public void removeDefaultRoute() {
-        if(mInterfaceName != null) {
-            mDefaultGatewayAddr = NetworkUtils.getDefaultRoute(mInterfaceName);
-            NetworkUtils.removeDefaultRoute(mInterfaceName);
-        }
-    }
-
-    public void restoreDefaultRoute() {
-        // 0 is not a valid address for a gateway
-        if (mInterfaceName != null && mDefaultGatewayAddr != 0) {
-            NetworkUtils.setDefaultRoute(mInterfaceName, mDefaultGatewayAddr);
-        }
-    }
-
     private void getPhoneService(boolean forceRefresh) {
         if ((mPhoneService == null) || forceRefresh) {
             mPhoneService = ITelephony.Stub.asInterface(ServiceManager.getService("phone"));
@@ -219,15 +232,6 @@
     }
 
     /**
-     * Return the IP addresses of the DNS servers available for the mobile data
-     * network interface.
-     * @return a list of DNS addresses, with no holes.
-     */
-    public String[] getNameServers() {
-        return getNameServerList(sDnsPropNames);
-    }
-
-    /**
      * {@inheritDoc}
      * The mobile data network subtype indicates what generation network technology is in effect,
      * e.g., GPRS, EDGE, UMTS, etc.
@@ -273,54 +277,19 @@
      */
     @Override
     public boolean teardown() {
-        getPhoneService(false);
-        /*
-         * If the phone process has crashed in the past, we'll get a
-         * RemoteException and need to re-reference the service.
-         */
-        for (int retry = 0; retry < 2; retry++) {
-            if (mPhoneService == null) {
-                Log.w(TAG,
-                    "Ignoring mobile data teardown request because could not acquire PhoneService");
-                break;
-            }
-
-            try {
-                return mPhoneService.disableDataConnectivity();
-            } catch (RemoteException e) {
-                if (retry == 0) getPhoneService(true);
-            }
-        }
-
-        Log.w(TAG, "Failed to tear down mobile data connectivity");
-        return false;
+        mTeardownRequested = true;
+        return (setEnableApn(mApnType, false) != Phone.APN_REQUEST_FAILED);
     }
 
     /**
      * Re-enable mobile data connectivity after a {@link #teardown()}.
      */
     public boolean reconnect() {
-        getPhoneService(false);
-        /*
-         * If the phone process has crashed in the past, we'll get a
-         * RemoteException and need to re-reference the service.
-         */
-        for (int retry = 0; retry < 2; retry++) {
-            if (mPhoneService == null) {
-                Log.w(TAG,
-                    "Ignoring mobile data connect request because could not acquire PhoneService");
-                break;
-            }
-
-            try {
-                return mPhoneService.enableDataConnectivity();
-            } catch (RemoteException e) {
-                if (retry == 0) getPhoneService(true);
-            }
-        }
-
-        Log.w(TAG, "Failed to set up mobile data connectivity");
-        return false;
+        mEnabled = true;
+        mTeardownRequested = false;
+        mEnabled = (setEnableApn(mApnType, true) !=
+                Phone.APN_REQUEST_FAILED);
+        return mEnabled;
     }
 
     /**
@@ -374,14 +343,7 @@
      * </ul>
      */
     public int startUsingNetworkFeature(String feature, int callingPid, int callingUid) {
-        if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
-            mLastCallingPid = callingPid;
-            return setEnableApn(Phone.APN_TYPE_MMS, true);
-        } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
-            return setEnableApn(Phone.APN_TYPE_SUPL, true);
-        } else {
-            return -1;
-        }
+        return -1;
     }
 
     /**
@@ -397,13 +359,7 @@
      * the value {@code -1} always indicates failure.
      */
     public int stopUsingNetworkFeature(String feature, int callingPid, int callingUid) {
-        if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
-            return setEnableApn(Phone.APN_TYPE_MMS, false);
-        } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
-            return setEnableApn(Phone.APN_TYPE_SUPL, false);
-        } else {
-            return -1;
-        }
+        return -1;
     }
 
     /**
@@ -433,43 +389,6 @@
         return sb.toString();
     }
 
-    private void setupDnsProperties() {
-        mDnsServers.clear();
-        // Set up per-process DNS server list on behalf of the MMS process
-        int i = 1;
-        if (mInterfaceName != null) {
-            for (String propName : sDnsPropNames) {
-                if (propName.indexOf(mInterfaceName) != -1) {
-                    String propVal = SystemProperties.get(propName);
-                    if (propVal != null && propVal.length() != 0 && !propVal.equals("0.0.0.0")) {
-                        mDnsServers.add(propVal);
-                        if (mLastCallingPid != -1) {
-                            SystemProperties.set("net.dns"  + i + "." + mLastCallingPid, propVal);
-                        }
-                        ++i;
-                    }
-                }
-            }
-        }
-        if (i == 1) {
-            Log.d(TAG, "DNS server addresses are not known.");
-        } else if (mLastCallingPid != -1) {
-            /*
-            * Bump the property that tells the name resolver library
-            * to reread the DNS server list from the properties.
-            */
-            String propVal = SystemProperties.get("net.dnschange");
-            if (propVal.length() != 0) {
-                try {
-                    int n = Integer.parseInt(propVal);
-                    SystemProperties.set("net.dnschange", "" + (n+1));
-                } catch (NumberFormatException e) {
-                }
-            }
-        }
-        mLastCallingPid = -1;
-    }
-
    /**
      * Internal method supporting the ENABLE_MMS feature.
      * @param apnType the type of APN to be enabled or disabled (e.g., mms)
diff --git a/core/java/android/net/NetworkStateTracker.java b/core/java/android/net/NetworkStateTracker.java
index 37087ac..418f511 100644
--- a/core/java/android/net/NetworkStateTracker.java
+++ b/core/java/android/net/NetworkStateTracker.java
@@ -27,6 +27,7 @@
 import android.util.Config;
 import android.util.Log;
 
+
 /**
  * Each subclass of this class keeps track of the state of connectivity
  * of a network interface. All state information for a network should
@@ -40,11 +41,16 @@
     protected NetworkInfo mNetworkInfo;
     protected Context mContext;
     protected Handler mTarget;
+    protected String mInterfaceName;
+    protected String[] mDnsPropNames;
+    private boolean mPrivateDnsRouteSet;
+    protected int mDefaultGatewayAddr;
+    private boolean mDefaultRouteSet;
     private boolean mTeardownRequested;
 
-    private static boolean DBG = Config.LOGV; 
+    private static boolean DBG = Config.LOGV;
     private static final String TAG = "NetworkStateTracker";
-    
+
     public static final int EVENT_STATE_CHANGED = 1;
     public static final int EVENT_SCAN_RESULTS_AVAILABLE = 2;
     /**
@@ -56,6 +62,7 @@
     public static final int EVENT_CONFIGURATION_CHANGED = 4;
     public static final int EVENT_ROAMING_CHANGED = 5;
     public static final int EVENT_NETWORK_SUBTYPE_CHANGED = 6;
+    public static final int EVENT_RESTORE_DEFAULT_NETWORK = 7;
 
     public NetworkStateTracker(Context context,
             Handler target,
@@ -67,6 +74,7 @@
         mContext = context;
         mTarget = target;
         mTeardownRequested = false;
+
         this.mNetworkInfo = new NetworkInfo(networkType, subType, typeName, subtypeName);
     }
 
@@ -75,19 +83,21 @@
     }
 
     /**
-     * Return the list of DNS servers associated with this network.
-     * @return a list of the IP addresses of the DNS servers available
-     * for the network.
-     */
-    public abstract String[] getNameServers();
-
-    /**
      * Return the system properties name associated with the tcp buffer sizes
      * for this network.
      */
     public abstract String getTcpBufferSizesPropName();
 
     /**
+     * Return the IP addresses of the DNS servers available for the mobile data
+     * network interface.
+     * @return a list of DNS addresses, with no holes.
+     */
+    public String[] getNameServers() {
+        return getNameServerList(mDnsPropNames);
+    }
+
+    /**
      * Return the IP addresses of the DNS servers available for this
      * network interface.
      * @param propertyNames the names of the system properties whose values
@@ -112,6 +122,50 @@
         return dnsAddresses;
     }
 
+    public void addPrivateDnsRoutes() {
+        if (DBG) Log.d(TAG, "addPrivateDnsRoutes for " + this +
+                "(" + mInterfaceName + ")");
+        if (mInterfaceName != null && !mPrivateDnsRouteSet) {
+            for (String addrString : getNameServers()) {
+                int addr = NetworkUtils.lookupHost(addrString);
+                if (addr != -1) {
+                    NetworkUtils.addHostRoute(mInterfaceName, addr);
+                }
+            }
+            mPrivateDnsRouteSet = true;
+        }
+    }
+
+    public void removePrivateDnsRoutes() {
+        if (DBG) Log.d(TAG, "removePrivateDnsRoutes for " + this +
+                "(" + mInterfaceName + ")");
+        // TODO - we should do this explicitly but the NetUtils api doesnt
+        // support this yet - must remove all.  No worse than before
+        if (mInterfaceName != null && mPrivateDnsRouteSet) {
+            NetworkUtils.removeHostRoutes(mInterfaceName);
+            mPrivateDnsRouteSet = false;
+        }
+    }
+
+    public void addDefaultRoute() {
+        if (DBG) Log.d(TAG, "addDefaultRoute for " + this + "(" +
+                mInterfaceName + "), GatewayAddr=" + mDefaultGatewayAddr);
+        if ((mInterfaceName != null) && (mDefaultGatewayAddr != 0) &&
+                mDefaultRouteSet == false) {
+            NetworkUtils.setDefaultRoute(mInterfaceName, mDefaultGatewayAddr);
+            mDefaultRouteSet = true;
+        }
+    }
+
+    public void removeDefaultRoute() {
+        if (DBG) Log.d(TAG, "removeDefaultRoute for " + this + "(" +
+                mInterfaceName + ")");
+        if (mInterfaceName != null && mDefaultRouteSet == true) {
+            NetworkUtils.removeDefaultRoute(mInterfaceName);
+            mDefaultRouteSet = false;
+        }
+    }
+
     /**
      * Reads the network specific TCP buffer sizes from SystemProperties
      * net.tcp.buffersize.[default|wifi|umts|edge|gprs] and set them for system
@@ -209,6 +263,7 @@
      * @param extraInfo optional {@code String} providing extra information about the state change
      */
     public void setDetailedState(NetworkInfo.DetailedState state, String reason, String extraInfo) {
+        if (DBG) Log.d(TAG, "setDetailed state, old ="+mNetworkInfo.getDetailedState()+" and new state="+state);
         if (state != mNetworkInfo.getDetailedState()) {
             boolean wasConnecting = (mNetworkInfo.getState() == NetworkInfo.State.CONNECTING);
             String lastReason = mNetworkInfo.getReason();
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 830b0bd..1775a4b 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -120,9 +120,18 @@
          * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} permission to be
          * able to modify the contents of the SD card.  (Apps targeting
          * earlier versions will always request the permission.)
+         * <li> They must explicitly request the
+         * {@link android.Manifest.permission#READ_PHONE_STATE} permission to be
+         * able to be able to retrieve phone state info.  (Apps targeting
+         * earlier versions will always request the permission.)
+         * <li> They are assumed to support different screen densities and
+         * sizes.  (Apps targeting earlier versions are assumed to only support
+         * medium density normal size screens unless otherwise indicated).
+         * They can still explicitly specify screen support either way with the
+         * supports-screens manifest tag.
          * </ul>
          */
-        public static final int DONUT = CUR_DEVELOPMENT;
+        public static final int DONUT = 4;
     }
     
     /** The type of build, like "user" or "eng". */
diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
index c3ae3c2..4a036ec 100644
--- a/core/java/android/os/SystemProperties.java
+++ b/core/java/android/os/SystemProperties.java
@@ -30,6 +30,9 @@
 
     private static native String native_get(String key);
     private static native String native_get(String key, String def);
+    private static native int native_get_int(String key, int def);
+    private static native long native_get_long(String key, long def);
+    private static native boolean native_get_boolean(String key, boolean def);
     private static native void native_set(String key, String def);
 
     /**
@@ -65,11 +68,10 @@
      * @throws IllegalArgumentException if the key exceeds 32 characters
      */
     public static int getInt(String key, int def) {
-        try {
-            return Integer.parseInt(get(key));
-        } catch (NumberFormatException e) {
-            return def;
+        if (key.length() > PROP_NAME_MAX) {
+            throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX);
         }
+        return native_get_int(key, def);
     }
 
     /**
@@ -81,11 +83,10 @@
      * @throws IllegalArgumentException if the key exceeds 32 characters
      */
     public static long getLong(String key, long def) {
-        try {
-            return Long.parseLong(get(key));
-        } catch (NumberFormatException e) {
-            return def;
+        if (key.length() > PROP_NAME_MAX) {
+            throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX);
         }
+        return native_get_long(key, def);
     }
 
     /**
@@ -102,27 +103,10 @@
      * @throws IllegalArgumentException if the key exceeds 32 characters
      */
     public static boolean getBoolean(String key, boolean def) {
-        String value = get(key);
-        // Deal with these quick cases first: not found, 0 and 1
-        if (value.equals("")) {
-            return def;
-        } else if (value.equals("0")) {
-            return false;
-        } else if (value.equals("1")) {
-            return true;
-        // now for slower (and hopefully less common) cases
-        } else if (value.equalsIgnoreCase("n") ||
-                   value.equalsIgnoreCase("no") ||
-                   value.equalsIgnoreCase("false") ||
-                   value.equalsIgnoreCase("off")) {
-            return false;
-        } else if (value.equalsIgnoreCase("y") ||
-                   value.equalsIgnoreCase("yes") ||
-                   value.equalsIgnoreCase("true") ||
-                   value.equalsIgnoreCase("on")) {
-            return true;
+        if (key.length() > PROP_NAME_MAX) {
+            throw new IllegalArgumentException("key.length > " + PROP_NAME_MAX);
         }
-        return def;
+        return native_get_boolean(key, def);
     }
 
     /**
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 066401f..7a1a9e4 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -177,36 +177,6 @@
         public static final String DISPLAY_NAME = "display_name";
 
         /**
-         * Reference to the row in the data table holding the primary phone number.
-         * <P>Type: INTEGER REFERENCES data(_id)</P>
-         */
-        @Deprecated
-        public static final String PRIMARY_PHONE_ID = "primary_phone_id";
-
-        /**
-         * Reference to the row in the data table holding the default phone number.
-         * If the contact has only one phone number, that number is the default one.
-         * Otherwise it is the one explicitly selected by the user as primary.
-         * <P>Type: INTEGER REFERENCES data(_id)</P>
-         */
-        public static final String DEFAULT_PHONE_ID = "default_phone_id";
-
-        /**
-         * Reference to the row in the data table holding the primary email address.
-         * <P>Type: INTEGER REFERENCES data(_id)</P>
-         */
-        @Deprecated
-        public static final String PRIMARY_EMAIL_ID = "primary_email_id";
-
-        /**
-         * Reference to the row in the data table holding the default email address.
-         * If the contact has only one email address, that address is the default one.
-         * Otherwise it is the one explicitly selected by the user as primary.
-         * <P>Type: INTEGER REFERENCES data(_id)</P>
-         */
-        public static final String DEFAULT_EMAIL_ID = "default_email_id";
-
-        /**
          * Reference to the row in the data table holding the photo.
          * <P>Type: INTEGER REFERENCES data(_id)</P>
          */
@@ -225,43 +195,11 @@
         public static final String PRESENCE_STATUS = Presence.PRESENCE_STATUS;
 
         /**
-         * The type of data, for example Home or Work.
+         * An indicator of whether this contact has at least one phone number. "1" if there is
+         * at least one phone number, "0" otherwise.
          * <P>Type: INTEGER</P>
          */
-        @Deprecated
-        public static final String PRIMARY_PHONE_TYPE = CommonDataKinds.Phone.TYPE;
-
-        /**
-         * The type of data, for example Home or Work.
-         * <P>Type: INTEGER</P>
-         */
-        public static final String DEFAULT_PHONE_TYPE = "default_phone_type";
-
-        /**
-         * The user defined label for the primary phone.
-         * <P>Type: TEXT</P>
-         */
-        @Deprecated
-        public static final String PRIMARY_PHONE_LABEL = CommonDataKinds.Phone.LABEL;
-
-        /**
-         * The user defined label for the default phone.
-         * <P>Type: TEXT</P>
-         */
-        public static final String DEFAULT_PHONE_LABEL = "default_phone_label";
-
-        /**
-         * The primary phone number.
-         * <P>Type: TEXT</P>
-         */
-        @Deprecated
-        public static final String PRIMARY_PHONE_NUMBER = CommonDataKinds.Phone.NUMBER;
-
-        /**
-         * The default phone number.
-         * <P>Type: TEXT</P>
-         */
-        public static final String DEFAULT_PHONE_NUMBER = "default_phone_number";
+        public static final String HAS_PHONE_NUMBER = "has_phone_number";
     }
 
     /**
@@ -857,7 +795,10 @@
 
             /**
              * The name that should be used to display the contact.
-             * <P>Type: TEXT</P>
+             * <i>Unstructured component of the name should be consistent with
+             * its structured representation.</i>
+             * <p>
+             * Type: TEXT
              */
             public static final String DISPLAY_NAME = "data9";
         }
@@ -1006,7 +947,8 @@
             public static final int TYPE_OTHER = 3;
 
             /**
-             * The full, unstructured postal address.
+             * The full, unstructured postal address. <i>This field must be
+             * consistent with any structured data.</i>
              * <p>
              * Type: TEXT
              */
@@ -1017,7 +959,9 @@
              * Also for 'in care of' or 'c/o'.
              * <p>
              * Type: TEXT
+             * @deprecated since this isn't supported by gd:structuredPostalAddress
              */
+            @Deprecated
             public static final String AGENT = "data4";
 
             /**
@@ -1025,7 +969,9 @@
              * necessarily numbers), eg. "The Pillars".
              * <p>
              * Type: TEXT
+             * @deprecated since this isn't supported by gd:structuredPostalAddress
              */
+            @Deprecated
             public static final String HOUSENAME = "data5";
 
             /**
@@ -1068,7 +1014,9 @@
              * intended for delivery addresses.
              * <p>
              * Type: TEXT
+             * @deprecated since this isn't supported by gd:structuredPostalAddress
              */
+            @Deprecated
             public static final String SUBREGION = "data10";
 
             /**
diff --git a/core/java/android/provider/Gmail.java b/core/java/android/provider/Gmail.java
index c4b29ae..5702e7c 100644
--- a/core/java/android/provider/Gmail.java
+++ b/core/java/android/provider/Gmail.java
@@ -83,7 +83,7 @@
     public static final String LABEL_OUTBOX = "^^out";
 
     public static final String AUTHORITY = "gmail-ls";
-    private static final String TAG = "gmail-ls";
+    private static final String TAG = "Gmail";
     private static final String AUTHORITY_PLUS_CONVERSATIONS =
             "content://" + AUTHORITY + "/conversations/";
     private static final String AUTHORITY_PLUS_LABELS =
diff --git a/core/java/android/provider/Im.java b/core/java/android/provider/Im.java
index a054132..b11abe8 100644
--- a/core/java/android/provider/Im.java
+++ b/core/java/android/provider/Im.java
@@ -2101,17 +2101,60 @@
 
     }
 
+
+    /**
+     * Columns for IM branding resource map cache table. This table caches the result of
+     * loading the branding resources to speed up IM landing page start.
+     */
+    public interface BrandingResourceMapCacheColumns {
+        /**
+         * The provider ID
+         * <P>Type: INTEGER</P>
+         */
+        String PROVIDER_ID = "provider_id";
+        /**
+         * The application resource ID
+         * <P>Type: INTEGER</P>
+         */
+        String APP_RES_ID = "app_res_id";
+        /**
+         * The plugin resource ID
+         * <P>Type: INTEGER</P>
+         */
+        String PLUGIN_RES_ID = "plugin_res_id";
+    }
+
+    /**
+     * The table for caching the result of loading IM branding resources.
+     */
+    public static final class BrandingResourceMapCache
+        implements BaseColumns, BrandingResourceMapCacheColumns {
+        /**
+         * The content:// style URL for this table.
+         */
+        public static final Uri CONTENT_URI = Uri.parse("content://im/brandingResMapCache");
+    }
+
+
+
+    /**
+     * //TODO: move these to MCS specific provider.
+     * The following are MCS stuff, and should really live in a separate provider specific to
+     * MCS code.
+     */
+
     /**
      * Columns from OutgoingRmq table
      */
     public interface OutgoingRmqColumns {
         String RMQ_ID = "rmq_id";
-        String TYPE = "type";
         String TIMESTAMP = "ts";
         String DATA = "data";
+        String PROTOBUF_TAG = "type";
     }
 
     /**
+     * //TODO: we should really move these to their own provider and database.
      * The table for storing outgoing rmq packets.
      */
     public static final class OutgoingRmq implements BaseColumns, OutgoingRmqColumns {
@@ -2174,6 +2217,7 @@
     }
 
     /**
+     * //TODO: move these out into their own provider and database
      * The table for storing the last client rmq id sent to the server.
      */
     public static final class LastRmqId implements BaseColumns, LastRmqIdColumns {
@@ -2234,35 +2278,21 @@
     }
 
     /**
-     * Columns for IM branding resource map cache table. This table caches the result of
-     * loading the branding resources to speed up IM landing page start.
+     * Columns for the s2dRmqIds table, which stores the server-to-device message
+     * persistent ids. These are used in the RMQ2 protocol, where in the login request, the
+     * client selective acks these s2d ids to the server.
      */
-    public interface BrandingResourceMapCacheColumns {
-        /**
-         * The provider ID
-         * <P>Type: INTEGER</P>
-         */
-        String PROVIDER_ID = "provider_id";
-        /**
-         * The application resource ID
-         * <P>Type: INTEGER</P>
-         */
-        String APP_RES_ID = "app_res_id";
-        /**
-         * The plugin resource ID
-         * <P>Type: INTEGER</P>
-         */
-        String PLUGIN_RES_ID = "plugin_res_id";
+    public interface ServerToDeviceRmqIdsColumn {
+        String RMQ_ID = "rmq_id";
     }
 
-    /**
-     * The table for caching the result of loading IM branding resources.
-     */
-    public static final class BrandingResourceMapCache
-        implements BaseColumns, BrandingResourceMapCacheColumns {
+    public static final class ServerToDeviceRmqIds implements BaseColumns,
+            ServerToDeviceRmqIdsColumn {
+
         /**
          * The content:// style URL for this table.
          */
-        public static final Uri CONTENT_URI = Uri.parse("content://im/brandingResMapCache");
+        public static final Uri CONTENT_URI = Uri.parse("content://im/s2dids");
     }
+
 }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e1b8e99..85a2041 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2908,7 +2908,52 @@
          * the retrying.
          */
         public static final String GTALK_MAX_RETRIES_FOR_AUTH_EXPIRED =
-            "gtalk_max_retries_for_auth_expired";
+                "gtalk_max_retries_for_auth_expired";
+
+        /**
+         * a boolean setting indicating whether the GTalkService should use RMQ2 protocol or not.
+         */
+        public static final String GTALK_USE_RMQ2_PROTOCOL =
+                "gtalk_use_rmq2";
+
+        /**
+         * a boolean setting indicating whether the GTalkService should support both RMQ and
+         * RMQ2 protocols. This setting is true for the transitional period when we need to
+         * support both protocols.
+         */
+        public static final String GTALK_SUPPORT_RMQ_AND_RMQ2_PROTOCOLS =
+                "gtalk_support_rmq_and_rmq2";
+
+        /**
+         * a boolean setting controlling whether the rmq2 protocol will include stream ids in
+         * the protobufs. This is used for debugging.
+         */
+        public static final String GTALK_RMQ2_INCLUDE_STREAM_ID =
+                "gtalk_rmq2_include_stream_id";
+
+        /**
+         * This is gdata url to lookup album and picture info from picasa web.
+         */
+        public static final String GTALK_PICASA_ALBUM_URL =
+                "gtalk_picasa_album_url";
+
+        /**
+         * This is the url to lookup picture info from flickr.
+         */
+        public static final String GTALK_FLICKR_PHOTO_INFO_URL =
+                "gtalk_flickr_photo_info_url";
+
+        /**
+         * This is the url to lookup an actual picture from flickr.
+         */
+        public static final String GTALK_FLICKR_PHOTO_URL =
+                "gtalk_flickr_photo_url";
+
+        /**
+         * This is the gdata url to lookup info on a youtube video.
+         */
+        public static final String GTALK_YOUTUBE_VIDEO_URL =
+                "gtalk_youtube_video_url";
 
         /**
          * This is the url for getting the app token for server-to-device push messaging.
@@ -2916,37 +2961,6 @@
         public static final String PUSH_MESSAGING_REGISTRATION_URL =
                 "push_messaging_registration_url";
 
-        /**
-         * This is gdata url to lookup album and picture info from picasa web.
-         */
-        public static final String GTALK_PICASA_ALBUM_URL =
-            "gtalk_picasa_album_url";
-
-        /**
-         * This is the url to lookup picture info from flickr.
-         */
-        public static final String GTALK_FLICKR_PHOTO_INFO_URL =
-            "gtalk_flickr_photo_info_url";
-
-        /**
-         * This is the url to lookup an actual picture from flickr.
-         */
-        public static final String GTALK_FLICKR_PHOTO_URL =
-            "gtalk_flickr_photo_url";
-
-        /**
-         * This is the gdata url to lookup info on a youtube video.
-         */
-        public static final String GTALK_YOUTUBE_VIDEO_URL =
-            "gtalk_youtube_video_url";
-
-
-        /**
-         * This is the url for getting the app token for server-to-device data messaging.
-         */
-        public static final String DATA_MESSAGE_GET_APP_TOKEN_URL =
-                "data_messaging_get_app_token_url";
-
 	/**
 	 * Use android://&lt;it&gt; routing infos for Google Sync Server subcriptions.
 	 */
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 7017514..595b10c 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -24,7 +24,6 @@
 import android.app.WallpaperManager;
 import android.content.Intent;
 import android.graphics.Rect;
-import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
 import android.os.RemoteException;
@@ -33,6 +32,7 @@
 import android.view.IWindowSession;
 import android.view.SurfaceHolder;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.ViewRoot;
 import android.view.WindowManager;
 import android.view.WindowManagerImpl;
@@ -50,13 +50,14 @@
         "android.service.wallpaper.WallpaperService";
 
     static final String TAG = "WallpaperService";
-    static final boolean DEBUG = true;
+    static final boolean DEBUG = false;
     
     private static final int DO_ATTACH = 10;
     private static final int DO_DETACH = 20;
     
     private static final int MSG_UPDATE_SURFACE = 10000;
     private static final int MSG_VISIBILITY_CHANGED = 10010;
+    private static final int MSG_WALLPAPER_OFFSETS = 10020;
     
     /**
      * The actual implementation of a wallpaper.  A wallpaper service may
@@ -83,6 +84,8 @@
         int mHeight;
         int mFormat;
         int mType;
+        int mCurWidth;
+        int mCurHeight;
         boolean mDestroyReportNeeded;
         final Rect mVisibleInsets = new Rect();
         final Rect mWinFrame = new Rect();
@@ -92,6 +95,11 @@
                 = new WindowManager.LayoutParams();
         IWindowSession mSession;
 
+        final Object mLock = new Object();
+        boolean mOffsetMessageEnqueued;
+        float mPendingXOffset;
+        float mPendingYOffset;
+        
         final BaseSurfaceHolder mSurfaceHolder = new BaseSurfaceHolder() {
 
             @Override
@@ -127,6 +135,20 @@
                         visible ? 1 : 0);
                 mCaller.sendMessage(msg);
             }
+
+            @Override
+            public void dispatchWallpaperOffsets(float x, float y) {
+                synchronized (mLock) {
+                    mPendingXOffset = x;
+                    mPendingYOffset = y;
+                    if (!mOffsetMessageEnqueued) {
+                        mOffsetMessageEnqueued = true;
+                        Message msg = mCaller.obtainMessage(MSG_WALLPAPER_OFFSETS);
+                        mCaller.sendMessage(msg);
+                    }
+                }
+            }
+            
         };
         
         /**
@@ -178,6 +200,16 @@
         }
         
         /**
+         * Called to inform you of the wallpaper's offsets changing
+         * within its contain, corresponding to the container's
+         * call to {@link WallpaperManager#setWallpaperOffsets(IBinder, float, float)
+         * WallpaperManager.setWallpaperOffsets()}.
+         */
+        public void onOffsetsChanged(float xOffset, float yOffset,
+                int xPixelOffset, int yPixelOffset) {
+        }
+        
+        /**
          * Convenience for {@link SurfaceHolder.Callback#surfaceChanged
          * SurfaceHolder.Callback.surfaceChanged()}.
          */
@@ -200,9 +232,9 @@
 
         void updateSurface(boolean force) {
             int myWidth = mSurfaceHolder.getRequestedWidth();
-            if (myWidth <= 0) myWidth = mIWallpaperEngine.mReqWidth;
+            if (myWidth <= 0) myWidth = ViewGroup.LayoutParams.FILL_PARENT;
             int myHeight = mSurfaceHolder.getRequestedHeight();
-            if (myHeight <= 0) myHeight = mIWallpaperEngine.mReqHeight;
+            if (myHeight <= 0) myHeight = ViewGroup.LayoutParams.FILL_PARENT;
             
             final boolean creating = !mCreated;
             final boolean formatChanged = mFormat != mSurfaceHolder.getRequestedFormat();
@@ -254,6 +286,9 @@
                     if (DEBUG) Log.i(TAG, "New surface: " + mSurfaceHolder.mSurface
                             + ", frame=" + mWinFrame);
                     
+                    mCurWidth = mWinFrame.width();
+                    mCurHeight = mWinFrame.height();
+                    
                     mSurfaceHolder.mSurfaceLock.unlock();
 
                     try {
@@ -278,10 +313,12 @@
                             }
                         }
                         if (creating || formatChanged || sizeChanged) {
-                            onSurfaceChanged(mSurfaceHolder, mFormat, mWidth, mHeight);
+                            onSurfaceChanged(mSurfaceHolder, mFormat,
+                                    mCurWidth, mCurHeight);
                             if (callbacks != null) {
                                 for (SurfaceHolder.Callback c : callbacks) {
-                                    c.surfaceChanged(mSurfaceHolder, mFormat, mWidth, mHeight);
+                                    c.surfaceChanged(mSurfaceHolder, mFormat,
+                                            mCurWidth, mCurHeight);
                                 }
                             }
                         }
@@ -305,7 +342,10 @@
             mCaller = wrapper.mCaller;
             mConnection = wrapper.mConnection;
             mWindowToken = wrapper.mWindowToken;
-            mSurfaceHolder.setSizeFromLayout();
+            // XXX temp -- should run in size from layout (screen) mode.
+            mSurfaceHolder.setFixedSize(mIWallpaperEngine.mReqWidth,
+                    mIWallpaperEngine.mReqHeight);
+            //mSurfaceHolder.setSizeFromLayout();
             mInitializing = true;
             mSession = ViewRoot.getWindowSession(getMainLooper());
             mWindow.setSession(mSession);
@@ -396,6 +436,22 @@
                             + ": " + message.arg1);
                     mEngine.onVisibilityChanged(message.arg1 != 0);
                     break;
+                case MSG_WALLPAPER_OFFSETS: {
+                    float xOffset;
+                    float yOffset;
+                    synchronized (mEngine.mLock) {
+                        xOffset = mEngine.mPendingXOffset;
+                        yOffset = mEngine.mPendingYOffset;
+                        mEngine.mOffsetMessageEnqueued = false;
+                    }
+                    if (DEBUG) Log.v(TAG, "Offsets change in " + mEngine
+                            + ": " + xOffset + "," + yOffset);
+                    final int availw = mReqWidth-mEngine.mCurWidth;
+                    final int xPixels = availw > 0 ? -(int)(availw*xOffset+.5f) : 0;
+                    final int availh = mReqHeight-mEngine.mCurHeight;
+                    final int yPixels = availh > 0 ? -(int)(availh*yOffset+.5f) : 0;
+                    mEngine.onOffsetsChanged(xOffset, yOffset, xPixels, yPixels);
+                } break;
                 default :
                     Log.w(TAG, "Unknown message type " + message.what);
             }
diff --git a/core/java/android/speech/RecognitionResult.java b/core/java/android/speech/RecognitionResult.java
index 8d031fc..978106b 100644
--- a/core/java/android/speech/RecognitionResult.java
+++ b/core/java/android/speech/RecognitionResult.java
@@ -60,9 +60,11 @@
      * 
      * @param contact the contact name.
      * @param phoneType the phone type.
+     * @param callAction whether this result included a command to "call", or just the contact name.
      */
-    public static RecognitionResult newContactResult(String contact, int phoneType) {
-        return new RecognitionResult(CONTACT_RESULT, contact, phoneType);
+    public static RecognitionResult newContactResult(String contact, int phoneType,
+            boolean callAction) {
+        return new RecognitionResult(CONTACT_RESULT, contact, phoneType, callAction);
     }
 
     /**
@@ -112,8 +114,16 @@
      */
     public final String mUrl;
 
-    /** Phone number type. This is valid only when mResultType == CONTACT_RESULT */
+    /**
+     * Phone number type. This is valid only when mResultType == CONTACT_RESULT.
+     */
     public final int mPhoneType;
+    
+    /**
+     * Whether a contact recognition result included a command to "call". This is valid only
+     * when mResultType == CONTACT_RESULT.
+     */
+    public final boolean mCallAction;
 
     private RecognitionResult(int type, String query, String html, String url) {
         mResultType = type;
@@ -121,14 +131,16 @@
         mHtml = html;
         mUrl = url;
         mPhoneType = -1;
+        mCallAction = false;
     }
 
-    private RecognitionResult(int type, String query, int at) {
+    private RecognitionResult(int type, String query, int phoneType, boolean callAction) {
         mResultType = type;
         mText = query;
-        mPhoneType = at;
+        mPhoneType = phoneType;
         mHtml = null;
         mUrl = null;
+        mCallAction = callAction;
     }
     
     private RecognitionResult(Parcel in) {
@@ -137,6 +149,7 @@
         mHtml= in.readString();
         mUrl= in.readString();
         mPhoneType = in.readInt();
+        mCallAction = (in.readInt() == 1);
     }
 
     public void writeToParcel(Parcel out, int flags) {
@@ -145,6 +158,7 @@
         out.writeString(mHtml);
         out.writeString(mUrl);
         out.writeInt(mPhoneType);
+        out.writeInt(mCallAction ? 1 : 0);
     }
     
     
diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java
index 04a0ec8..4405a53 100755
--- a/core/java/android/speech/tts/TextToSpeech.java
+++ b/core/java/android/speech/tts/TextToSpeech.java
@@ -1032,7 +1032,7 @@
             }
             try {
                 String[] locStrings =  mITts.getLanguage();
-                if (locStrings.length == 3) {
+                if ((locStrings != null) && (locStrings.length == 3)) {
                     return new Locale(locStrings[0], locStrings[1], locStrings[2]);
                 } else {
                     return null;
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index c133cf2..f0a5ffd 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -968,7 +968,13 @@
             fm.bottom = bottom;
 
             for (int i = 0; i < chooseht.length; i++) {
-                chooseht[i].chooseHeight(text, start, end, choosehtv[i], v, fm);
+                if (chooseht[i] instanceof LineHeightSpan.WithDensity) {
+                    ((LineHeightSpan.WithDensity) chooseht[i]).
+                        chooseHeight(text, start, end, choosehtv[i], v, fm, paint);
+
+                } else {
+                    chooseht[i].chooseHeight(text, start, end, choosehtv[i], v, fm);
+                }
             }
 
             above = fm.ascent;
diff --git a/core/java/android/text/TextPaint.java b/core/java/android/text/TextPaint.java
index f13820d..f9e7cac 100644
--- a/core/java/android/text/TextPaint.java
+++ b/core/java/android/text/TextPaint.java
@@ -27,6 +27,7 @@
     public int baselineShift;
     public int linkColor;
     public int[] drawableState;
+    public float density = 1.0f;
 
     public TextPaint() {
         super();
@@ -51,5 +52,6 @@
         baselineShift = tp.baselineShift;
         linkColor = tp.linkColor;
         drawableState = tp.drawableState;
+        density = tp.density;
     }
 }
diff --git a/core/java/android/text/method/QwertyKeyListener.java b/core/java/android/text/method/QwertyKeyListener.java
index e420c27..172e9ac 100644
--- a/core/java/android/text/method/QwertyKeyListener.java
+++ b/core/java/android/text/method/QwertyKeyListener.java
@@ -434,7 +434,7 @@
         PICKER_SETS.put('y', "\u00FD\u00FF");
         PICKER_SETS.put('z', "\u017A\u017C\u017E");
         PICKER_SETS.put(KeyCharacterMap.PICKER_DIALOG_INPUT,
-                             "\u2026\u00A5\u2022\u00AE\u00A9\u00B1");
+                             "\u2026\u00A5\u2022\u00AE\u00A9\u00B1[]{}\\");
     };
 
     private boolean showCharacterPicker(View view, Editable content, char c,
diff --git a/core/java/android/text/style/AbsoluteSizeSpan.java b/core/java/android/text/style/AbsoluteSizeSpan.java
index 484f8ce..1214040 100644
--- a/core/java/android/text/style/AbsoluteSizeSpan.java
+++ b/core/java/android/text/style/AbsoluteSizeSpan.java
@@ -24,13 +24,28 @@
 public class AbsoluteSizeSpan extends MetricAffectingSpan implements ParcelableSpan {
 
     private final int mSize;
+    private boolean mDip;
 
+    /**
+     * Set the text size to <code>size</code> physical pixels.
+     */
     public AbsoluteSizeSpan(int size) {
         mSize = size;
     }
 
+    /**
+     * Set the text size to <code>size</code> physical pixels,
+     * or to <code>size</code> device-independent pixels if
+     * <code>dip</code> is true.
+     */
+    public AbsoluteSizeSpan(int size, boolean dip) {
+        mSize = size;
+        mDip = dip;
+    }
+
     public AbsoluteSizeSpan(Parcel src) {
         mSize = src.readInt();
+        mDip = src.readInt() != 0;
     }
     
     public int getSpanTypeId() {
@@ -43,19 +58,32 @@
 
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(mSize);
+        dest.writeInt(mDip ? 1 : 0);
     }
 
     public int getSize() {
         return mSize;
     }
 
+    public boolean getDip() {
+        return mDip;
+    }
+
     @Override
     public void updateDrawState(TextPaint ds) {
-        ds.setTextSize(mSize);
+        if (mDip) {
+            ds.setTextSize(mSize * ds.density);
+        } else {
+            ds.setTextSize(mSize);
+        }
     }
 
     @Override
     public void updateMeasureState(TextPaint ds) {
-        ds.setTextSize(mSize);
+        if (mDip) {
+            ds.setTextSize(mSize * ds.density);
+        } else {
+            ds.setTextSize(mSize);
+        }
     }
 }
diff --git a/core/java/android/text/style/LineHeightSpan.java b/core/java/android/text/style/LineHeightSpan.java
index c0ef97c..44a1706 100644
--- a/core/java/android/text/style/LineHeightSpan.java
+++ b/core/java/android/text/style/LineHeightSpan.java
@@ -19,6 +19,7 @@
 import android.graphics.Paint;
 import android.graphics.Canvas;
 import android.text.Layout;
+import android.text.TextPaint;
 
 public interface LineHeightSpan
 extends ParagraphStyle, WrapTogetherSpan
@@ -26,4 +27,10 @@
     public void chooseHeight(CharSequence text, int start, int end,
                              int spanstartv, int v,
                              Paint.FontMetricsInt fm);
+
+    public interface WithDensity extends LineHeightSpan {
+        public void chooseHeight(CharSequence text, int start, int end,
+                                 int spanstartv, int v,
+                                 Paint.FontMetricsInt fm, TextPaint paint);
+    }
 }
diff --git a/core/java/android/util/MathUtils.java b/core/java/android/util/MathUtils.java
index c80d90f..b35dd1e 100644
--- a/core/java/android/util/MathUtils.java
+++ b/core/java/android/util/MathUtils.java
@@ -144,6 +144,14 @@
         return start + (stop - start) * amount;
     }
     
+    public static float norm(float start, float stop, float value) {
+        return (value - start) / (stop - start);
+    }
+    
+    public static float map(float minStart, float minStop, float maxStart, float maxStop, float value) {
+        return maxStart + (maxStart - maxStop) * ((value - minStart) / (minStop - minStart));
+    }
+
     public static int random(int howbig) {
         return (int) (sRandom.nextFloat() * howbig);
     }
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 99d5c0c..ec2036e 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -56,4 +56,9 @@
      * to date on the current state showing navigational focus (touch mode) too.
      */
     void windowFocusChanged(boolean hasFocus, boolean inTouchMode);
+    
+    /**
+     * Called for wallpaper windows when their offsets change.
+     */
+    void dispatchWallpaperOffsets(float x, float y);
 }
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 4546572..4840f27 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -16,6 +16,8 @@
 
 package android.view;
 
+import com.android.internal.view.BaseIWindow;
+
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.CompatibilityInfo.Translator;
@@ -280,7 +282,9 @@
             return;
         }
         ViewRoot viewRoot = (ViewRoot) getRootView().getParent();
-        mTranslator = viewRoot.mTranslator;
+        if (viewRoot != null) {
+            mTranslator = viewRoot.mTranslator;
+        }
 
         Resources res = getContext().getResources();
         if (mTranslator != null || !res.getCompatibilityInfo().supportsScreen()) {
@@ -435,7 +439,7 @@
         updateWindow(false);
     }
 
-    private static class MyWindow extends IWindow.Stub {
+    private static class MyWindow extends BaseIWindow {
         private final WeakReference<SurfaceView> mSurfaceView;
 
         public MyWindow(SurfaceView surfaceView) {
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index 216fc5e..4623bb5 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -2858,6 +2858,9 @@
                 }
             }
         }
+        
+        public void dispatchWallpaperOffsets(float x, float y) {
+        }
     }
 
     /**
diff --git a/core/java/android/webkit/CacheManager.java b/core/java/android/webkit/CacheManager.java
index d8f87cf..02e8d6f 100644
--- a/core/java/android/webkit/CacheManager.java
+++ b/core/java/android/webkit/CacheManager.java
@@ -426,13 +426,17 @@
         }
 
         cacheRet.contentLength = cacheRet.outFile.length();
-        if (checkCacheRedirect(cacheRet.httpStatusCode)) {
+        boolean redirect = checkCacheRedirect(cacheRet.httpStatusCode);
+        if (redirect) {
             // location is in database, no need to keep the file
             cacheRet.contentLength = 0;
             cacheRet.localPath = "";
-            cacheRet.outFile.delete();
-        } else if (cacheRet.contentLength == 0) {
-            cacheRet.outFile.delete();
+        }
+        if ((redirect || cacheRet.contentLength == 0)
+                && !cacheRet.outFile.delete()) {
+            Log.e(LOGTAG, cacheRet.outFile.getPath() + " delete failed.");
+        }
+        if (cacheRet.contentLength == 0) {
             return;
         }
 
@@ -467,7 +471,10 @@
                     // if mBaseDir doesn't exist, files can be null.
                     if (files != null) {
                         for (int i = 0; i < files.length; i++) {
-                            new File(mBaseDir, files[i]).delete();
+                            File f = new File(mBaseDir, files[i]);
+                            if (!f.delete()) {
+                                Log.e(LOGTAG, f.getPath() + " delete failed.");
+                            }
                         }
                     }
                 } catch (SecurityException e) {
@@ -495,7 +502,10 @@
             ArrayList<String> pathList = mDataBase.trimCache(CACHE_TRIM_AMOUNT);
             int size = pathList.size();
             for (int i = 0; i < size; i++) {
-                new File(mBaseDir, pathList.get(i)).delete();
+                File f = new File(mBaseDir, pathList.get(i));
+                if (!f.delete()) {
+                    Log.e(LOGTAG, f.getPath() + " delete failed.");
+                }
             }
         }
     }
diff --git a/core/java/android/webkit/FrameLoader.java b/core/java/android/webkit/FrameLoader.java
index 8298729..81ed367 100644
--- a/core/java/android/webkit/FrameLoader.java
+++ b/core/java/android/webkit/FrameLoader.java
@@ -95,17 +95,6 @@
     public boolean executeLoad() {
         String url = mListener.url();
 
-        // Attempt to decode the percent-encoded url.
-        try {
-            url = new String(URLUtil.decode(url.getBytes()));
-        } catch (IllegalArgumentException e) {
-            // Fail with a bad url error if the decode fails.
-            mListener.error(EventHandler.ERROR_BAD_URL,
-                    mListener.getContext().getString(
-                            com.android.internal.R.string.httpErrorBadUrl));
-            return false;
-        }
-
         if (URLUtil.isNetworkUrl(url)){
             if (mSettings.getBlockNetworkLoads()) {
                 mListener.error(EventHandler.ERROR_BAD_URL,
@@ -113,6 +102,13 @@
                                 com.android.internal.R.string.httpErrorBadUrl));
                 return false;
             }
+            // Make sure it is correctly URL encoded before sending the request
+            if (!URLUtil.verifyURLEncoding(url)) {
+                mListener.error(EventHandler.ERROR_BAD_URL,
+                        mListener.getContext().getString(
+                        com.android.internal.R.string.httpErrorBadUrl));
+                return false;
+            }
             mNetwork = Network.getInstance(mListener.getContext());
             return handleHTTPLoad();
         } else if (handleLocalFile(url, mListener, mSettings)) {
@@ -164,9 +160,6 @@
         populateStaticHeaders();
         populateHeaders();
 
-        // response was handled by UrlIntercept, don't issue HTTP request
-        if (handleUrlIntercept()) return true;
-
         // response was handled by Cache, don't issue HTTP request
         if (handleCache()) {
             // push the request data down to the LoadListener
@@ -204,7 +197,7 @@
     }
 
     /*
-     * This function is used by handleUrlInterecpt and handleCache to
+     * This function is used by handleCache to
      * setup a load from the byte stream in a CacheResult.
      */
     private void startCacheLoad(CacheResult result) {
@@ -220,30 +213,6 @@
     }
 
     /*
-     * This function is used by handleHTTPLoad to allow URL
-     * interception. This can be used to provide alternative load
-     * methods such as locally stored versions or for debugging.
-     *
-     * Returns true if the response was handled by UrlIntercept.
-     */
-    private boolean handleUrlIntercept() {
-        // Check if the URL can be served from UrlIntercept. If
-        // successful, return the data just like a cache hit.
-
-        PluginData data = UrlInterceptRegistry.getPluginData(
-                mListener.url(), mHeaders);
-
-        if(data != null) {
-            PluginContentLoader loader =
-                    new PluginContentLoader(mListener, data);
-            loader.load();
-            return true;
-        }
-        // Not intercepted. Carry on as normal.
-        return false;
-    }
-
-    /*
      * This function is used by the handleHTTPLoad to setup the cache headers
      * correctly.
      * Returns true if the response was handled from the cache
diff --git a/core/java/android/webkit/GeolocationService.java b/core/java/android/webkit/GeolocationService.java
new file mode 100755
index 0000000..78b25ba
--- /dev/null
+++ b/core/java/android/webkit/GeolocationService.java
@@ -0,0 +1,189 @@
+/*
+ * 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.webkit;
+
+import android.app.ActivityThread;
+import android.content.Context;
+import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
+import android.location.LocationProvider;
+import android.os.Bundle;
+import android.util.Log;
+import android.webkit.WebView;
+import android.webkit.WebViewCore;
+
+
+/**
+ * Implements the Java side of GeolocationServiceAndroid.
+ * @hide Pending API council review.
+ */
+public final class GeolocationService implements LocationListener {
+
+    // Log tag
+    private static final String TAG = "geolocationService";
+
+    private long mNativeObject;
+    private LocationManager mLocationManager;
+    private boolean mIsGpsEnabled;
+    private boolean mIsRunning;
+    private boolean mIsNetworkProviderAvailable;
+    private boolean mIsGpsProviderAvailable;
+
+    /**
+     * Constructor
+     * @param nativeObject The native object to which this object will report position updates and
+     *     errors.
+     */
+    public GeolocationService(long nativeObject) {
+        mNativeObject = nativeObject;
+        // Register newLocationAvailable with platform service.
+        ActivityThread thread = ActivityThread.systemMain();
+        Context context = thread.getApplication();
+        mLocationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
+        if (mLocationManager == null) {
+            Log.e(TAG, "Could not get location manager.");
+        }
+     }
+
+    /**
+     * Start listening for location updates.
+     */
+    public void start() {
+        registerForLocationUpdates();
+        mIsRunning = true;
+    }
+
+    /**
+     * Stop listening for location updates.
+     */
+    public void stop() {
+        unregisterFromLocationUpdates();
+        mIsRunning = false;
+    }
+
+    /**
+     * Sets whether to use the GPS.
+     * @param enable Whether to use the GPS.
+     */
+    public void setEnableGps(boolean enable) {
+        if (mIsGpsEnabled != enable) {
+            mIsGpsEnabled = enable;
+            if (mIsRunning) {
+                // There's no way to unregister from a single provider, so we can
+                // only unregister from all, then reregister with all but the GPS.
+                unregisterFromLocationUpdates();
+                registerForLocationUpdates();
+            }
+        }
+    }
+
+    /**
+     * LocationListener implementation.
+     * Called when the location has changed.
+     * @param location The new location, as a Location object.
+     */
+    public void onLocationChanged(Location location) {
+        // Callbacks from the system location sevice are queued to this thread, so it's possible
+        // that we receive callbacks after unregistering. At this point, the native object will no
+        // longer exist.
+        if (mIsRunning) {
+            nativeNewLocationAvailable(mNativeObject, location);
+        }
+    }
+
+    /**
+     * LocationListener implementation.
+     * Called when the provider status changes.
+     * @param provider The name of the provider.
+     * @param status The new status of the provider.
+     * @param extras an optional Bundle with provider specific data.
+     */
+    public void onStatusChanged(String providerName, int status, Bundle extras) {
+        boolean isAvailable = (status == LocationProvider.AVAILABLE);
+        if (LocationManager.NETWORK_PROVIDER.equals(providerName)) {
+            mIsNetworkProviderAvailable = isAvailable;
+        } else if (LocationManager.GPS_PROVIDER.equals(providerName)) {
+            mIsGpsProviderAvailable = isAvailable;
+        }
+        maybeReportError("The last location provider is no longer available");
+    }
+
+    /**
+     * LocationListener implementation.
+     * Called when the provider is enabled.
+     * @param provider The name of the location provider that is now enabled.
+     */
+    public void onProviderEnabled(String providerName) {
+        // No need to notify the native side. It's enough to start sending
+        // valid position fixes again.
+        if (LocationManager.NETWORK_PROVIDER.equals(providerName)) {
+            mIsNetworkProviderAvailable = true;
+        } else if (LocationManager.GPS_PROVIDER.equals(providerName)) {
+            mIsGpsProviderAvailable = true;
+        }
+    }
+
+    /**
+     * LocationListener implementation.
+     * Called when the provider is disabled.
+     * @param provider The name of the location provider that is now disabled.
+     */
+    public void onProviderDisabled(String providerName) {
+        if (LocationManager.NETWORK_PROVIDER.equals(providerName)) {
+            mIsNetworkProviderAvailable = false;
+        } else if (LocationManager.GPS_PROVIDER.equals(providerName)) {
+            mIsGpsProviderAvailable = false;
+        }
+        maybeReportError("The last location provider was disabled");
+    }
+
+    /**
+     * Registers this object with the location service.
+     */
+    private void registerForLocationUpdates() {
+        mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
+        mIsNetworkProviderAvailable = true;
+        if (mIsGpsEnabled) {
+            mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
+            mIsGpsProviderAvailable = true;
+        }
+    }
+
+    /**
+     * Unregisters this object from the location service.
+     */
+    private void unregisterFromLocationUpdates() {
+        mLocationManager.removeUpdates(this);
+    }
+
+    /**
+     * Reports an error if neither the network nor the GPS provider is available.
+     */
+    private void maybeReportError(String message) {
+        // Callbacks from the system location sevice are queued to this thread, so it's possible
+        // that we receive callbacks after unregistering. At this point, the native object will no
+        // longer exist.
+        if (mIsRunning && !mIsNetworkProviderAvailable && !mIsGpsProviderAvailable) {
+            nativeNewErrorAvailable(mNativeObject, message);
+        }
+    }
+
+    // Native functions
+    private static native void nativeNewLocationAvailable(long nativeObject, Location location);
+    private static native void nativeNewErrorAvailable(long nativeObject, String message);
+}
diff --git a/core/java/android/webkit/Plugin.java b/core/java/android/webkit/Plugin.java
index f83da99..302bea2 100644
--- a/core/java/android/webkit/Plugin.java
+++ b/core/java/android/webkit/Plugin.java
@@ -26,7 +26,11 @@
 /**
  * Represents a plugin (Java equivalent of the PluginPackageAndroid
  * C++ class in libs/WebKitLib/WebKit/WebCore/plugins/android/)
+ *
+ * @deprecated This interface was inteded to be used by Gears. Since Gears was
+ * deprecated, so is this class.
  */
+@Deprecated
 public class Plugin {
     public interface PreferencesClickHandler {
         public void handleClickEvent(Context context);
@@ -38,6 +42,10 @@
     private String mDescription;
     private PreferencesClickHandler mHandler;
 
+    /**
+     * @deprecated
+     */
+    @Deprecated
     public Plugin(String name,
                   String path,
                   String fileName,
@@ -49,49 +57,92 @@
         mHandler = new DefaultClickHandler();
     }
 
+    /**
+     * @deprecated
+     */
+    @Deprecated
     public String toString() {
         return mName;
     }
 
+    /**
+     * @deprecated
+     */
+    @Deprecated
     public String getName() {
         return mName;
     }
 
+    /**
+     * @deprecated
+     */
+    @Deprecated
     public String getPath() {
         return mPath;
     }
 
+    /**
+     * @deprecated
+     */
+    @Deprecated
     public String getFileName() {
         return mFileName;
     }
 
+    /**
+     * @deprecated
+     */
+    @Deprecated
     public String getDescription() {
         return mDescription;
     }
 
+    /**
+     * @deprecated
+     */
+    @Deprecated
     public void setName(String name) {
         mName = name;
     }
 
+    /**
+     * @deprecated
+     */
+    @Deprecated
     public void setPath(String path) {
         mPath = path;
     }
 
+    /**
+     * @deprecated
+     */
+    @Deprecated
     public void setFileName(String fileName) {
         mFileName = fileName;
     }
 
+    /**
+     * @deprecated
+     */
+    @Deprecated
     public void setDescription(String description) {
         mDescription = description;
     }
 
+    /**
+     * @deprecated
+     */
+    @Deprecated
     public void setClickHandler(PreferencesClickHandler handler) {
         mHandler = handler;
     }
 
    /**
     * Invokes the click handler for this plugin.
+    *
+    * @deprecated
     */
+    @Deprecated
     public void dispatchClickEvent(Context context) {
         if (mHandler != null) {
             mHandler.handleClickEvent(context);
@@ -100,11 +151,14 @@
 
    /**
     * Default click handler. The plugins should implement their own.
+    *
+    * @deprecated
     */
+    @Deprecated
     private class DefaultClickHandler implements PreferencesClickHandler,
                                                  DialogInterface.OnClickListener {
         private AlertDialog mDialog;
-
+        @Deprecated
         public void handleClickEvent(Context context) {
             // Show a simple popup dialog containing the description
             // string of the plugin.
@@ -117,7 +171,10 @@
                         .show();
             }
         }
-
+        /**
+         * @deprecated
+         */
+        @Deprecated
         public void onClick(DialogInterface dialog, int which) {
             mDialog.dismiss();
             mDialog = null;
diff --git a/core/java/android/webkit/PluginContentLoader.java b/core/java/android/webkit/PluginContentLoader.java
deleted file mode 100644
index 2069599..0000000
--- a/core/java/android/webkit/PluginContentLoader.java
+++ /dev/null
@@ -1,96 +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.webkit;
-
-import android.net.http.Headers;
-
-import java.io.InputStream;
-import java.util.*;
-
-import org.apache.http.util.CharArrayBuffer;
-
-/**
- * This class is a concrete implementation of StreamLoader that uses a
- * PluginData object as the source for the stream.
- */
-class PluginContentLoader extends StreamLoader {
-
-    private PluginData mData;  // Content source
-
-    /**
-     * Constructs a PluginDataLoader for use when loading content from
-     * a plugin.
-     *
-     * @param loadListener LoadListener to pass the content to
-     * @param data PluginData used as the source for the content.
-     */
-    PluginContentLoader(LoadListener loadListener, PluginData data) {
-        super(loadListener);
-        mData = data;
-    }
-
-    @Override
-    protected boolean setupStreamAndSendStatus() {
-        mDataStream = mData.getInputStream();
-        mContentLength = mData.getContentLength();
-        mHandler.status(1, 1, mData.getStatusCode(), "OK");
-        return true;
-    }
-
-    @Override
-    protected void buildHeaders(Headers headers) {
-        // Crate a CharArrayBuffer with an arbitrary initial capacity.
-        CharArrayBuffer buffer = new CharArrayBuffer(100);
-        Iterator<Map.Entry<String, String[]>> responseHeadersIt =
-                mData.getHeaders().entrySet().iterator();
-        while (responseHeadersIt.hasNext()) {
-            Map.Entry<String, String[]> entry = responseHeadersIt.next();
-            // Headers.parseHeader() expects lowercase keys, so keys
-            // such as "Accept-Ranges" will fail to parse.
-            //
-            // UrlInterceptHandler instances supply a mapping of
-            // lowercase key to [ unmodified key, value ], so for
-            // Headers.parseHeader() to succeed, we need to construct
-            // a string using the key (i.e. entry.getKey()) and the
-            // element denoting the header value in the
-            // [ unmodified key, value ] pair (i.e. entry.getValue()[1).
-            //
-            // The reason why UrlInterceptHandler instances supply such a
-            // mapping in the first place is historical. Early versions of
-            // the Gears plugin used java.net.HttpURLConnection, which always
-            // returned headers names as capitalized strings. When these were
-            // fed back into webkit, they failed to parse.
-            //
-            // Mewanwhile, Gears was modified to use Apache HTTP library
-            // instead, so this design is now obsolete. Changing it however,
-            // would require changes to the Gears C++ codebase and QA-ing and
-            // submitting a new binary to the Android tree. Given the
-            // timelines for the next Android release, we will not do this
-            // for now.
-            //
-            // TODO: fix C++ Gears to remove the need for this
-            // design.
-            String keyValue = entry.getKey() + ": " + entry.getValue()[1];
-            buffer.ensureCapacity(keyValue.length());
-            buffer.append(keyValue);
-            // Parse it into the header container.
-            headers.parseHeader(buffer);
-            // Clear the buffer
-            buffer.clear();
-        }
-    }
-}
diff --git a/core/java/android/webkit/PluginData.java b/core/java/android/webkit/PluginData.java
index 02be1f7..d9b196a 100644
--- a/core/java/android/webkit/PluginData.java
+++ b/core/java/android/webkit/PluginData.java
@@ -28,7 +28,10 @@
  * status code. The PluginData class is the container for all these
  * parts.
  *
+ * @deprecated This class was inteded to be used by Gears. Since Gears was
+ * deprecated, so is this class.
  */
+@Deprecated
 public final class PluginData {
     /**
      * The content stream.
@@ -59,7 +62,10 @@
      * @param headers The response headers. Map of
      * lowercase header name to [ unmodified header name, header value]
      * @param length The HTTP response status code.
+     *
+     * @deprecated
      */
+    @Deprecated
     public PluginData(
             InputStream stream,
             long length,
@@ -75,7 +81,10 @@
      * Returns the input stream that contains the plugin content.
      *
      * @return An InputStream instance with the plugin content.
+     *
+     * @deprecated
      */
+    @Deprecated
     public InputStream getInputStream() {
         return mStream;
     }
@@ -84,7 +93,10 @@
      * Returns the length of the plugin content.
      *
      * @return the length of the plugin content.
+     *
+     * @deprecated
      */
+    @Deprecated
     public long getContentLength() {
         return mContentLength;
     }
@@ -96,7 +108,10 @@
      * @return A Map<String, String[]> containing all headers. The
      * mapping is 'lowercase header name' to ['unmodified header
      * name', header value].
+     *
+     * @deprecated
      */
+    @Deprecated
     public Map<String, String[]> getHeaders() {
         return mHeaders;
     }
@@ -105,7 +120,10 @@
      * Returns the HTTP status code for the response.
      *
      * @return The HTTP statue code, e.g 200.
+     *
+     * @deprecated
      */
+    @Deprecated
     public int getStatusCode() {
         return mStatusCode;
     }
diff --git a/core/java/android/webkit/PluginList.java b/core/java/android/webkit/PluginList.java
index a9d3d8c..5b65b9a 100644
--- a/core/java/android/webkit/PluginList.java
+++ b/core/java/android/webkit/PluginList.java
@@ -24,27 +24,40 @@
  * A simple list of initialized plugins. This list gets
  * populated when the plugins are initialized (at
  * browser startup, at the moment).
+ *
+ * @deprecated This interface was inteded to be used by Gears. Since Gears was
+ * deprecated, so is this class.
  */
+@Deprecated
 public class PluginList {
     private ArrayList<Plugin> mPlugins;
 
    /**
     * Public constructor. Initializes the list of plugins.
+    *
+    * @deprecated
     */
+    @Deprecated
     public PluginList() {
         mPlugins = new ArrayList<Plugin>();
     }
 
    /**
     * Returns the list of plugins as a java.util.List.
+    *
+    * @deprecated
     */
+    @Deprecated
     public synchronized List getList() {
         return mPlugins;
     }
 
    /**
     * Adds a plugin to the list.
+    *
+    * @deprecated
     */
+    @Deprecated
     public synchronized void addPlugin(Plugin plugin) {
         if (!mPlugins.contains(plugin)) {
             mPlugins.add(plugin);
@@ -53,7 +66,10 @@
 
    /**
     * Removes a plugin from the list.
+    *
+    * @deprecated
     */
+    @Deprecated
     public synchronized void removePlugin(Plugin plugin) {
         int location = mPlugins.indexOf(plugin);
         if (location != -1) {
@@ -63,14 +79,20 @@
 
    /**
     * Clears the plugin list.
+    *
+    * @deprecated
     */
+    @Deprecated
     public synchronized void clear() {
         mPlugins.clear();
     }
 
    /**
     * Dispatches the click event to the appropriate plugin.
+    *
+    * @deprecated
     */
+    @Deprecated
     public synchronized void pluginClicked(Context context, int position) {
         try {
             Plugin plugin = mPlugins.get(position);
diff --git a/core/java/android/webkit/URLUtil.java b/core/java/android/webkit/URLUtil.java
index 1d18289..5ed42e9 100644
--- a/core/java/android/webkit/URLUtil.java
+++ b/core/java/android/webkit/URLUtil.java
@@ -126,6 +126,32 @@
         return retData;
     }
 
+    /**
+     * @return True iff the url is correctly URL encoded
+     */
+    static boolean verifyURLEncoding(String url) {
+        int count = url.length();
+        if (count == 0) {
+            return false;
+        }
+
+        int index = url.indexOf('%');
+        while (index >= 0 && index < count) {
+            if (index < count - 2) {
+                try {
+                    parseHex((byte) url.charAt(++index));
+                    parseHex((byte) url.charAt(++index));
+                } catch (IllegalArgumentException e) {
+                    return false;
+                }
+            } else {
+                return false;
+            }
+            index = url.indexOf('%', index + 1);
+        }
+        return true;
+    }
+
     private static int parseHex(byte b) {
         if (b >= '0' && b <= '9') return (b - '0');
         if (b >= 'A' && b <= 'F') return (b - 'A' + 10);
diff --git a/core/java/android/webkit/UrlInterceptHandler.java b/core/java/android/webkit/UrlInterceptHandler.java
index 9216413..78bab04 100644
--- a/core/java/android/webkit/UrlInterceptHandler.java
+++ b/core/java/android/webkit/UrlInterceptHandler.java
@@ -20,6 +20,11 @@
 import android.webkit.PluginData;
 import java.util.Map;
 
+/**
+ * @deprecated This interface was inteded to be used by Gears. Since Gears was
+ * deprecated, so is this class.
+ */
+@Deprecated
 public interface UrlInterceptHandler {
 
     /**
@@ -30,8 +35,8 @@
      * @param url URL string.
      * @param headers The headers associated with the request. May be null.
      * @return The CacheResult containing the surrogate response.
-     * @Deprecated Use PluginData getPluginData(String url,
-     * Map<String, String> headers); instead
+     *
+     * @deprecated Do not use, this interface is deprecated.
      */
     @Deprecated
     public CacheResult service(String url, Map<String, String> headers);
@@ -44,6 +49,9 @@
      * @param url URL string.
      * @param headers The headers associated with the request. May be null.
      * @return The PluginData containing the surrogate response.
+     *
+     * @deprecated Do not use, this interface is deprecated.
      */
+    @Deprecated
     public PluginData getPluginData(String url, Map<String, String> headers);
 }
diff --git a/core/java/android/webkit/UrlInterceptRegistry.java b/core/java/android/webkit/UrlInterceptRegistry.java
index 6051f29..6e2a482 100644
--- a/core/java/android/webkit/UrlInterceptRegistry.java
+++ b/core/java/android/webkit/UrlInterceptRegistry.java
@@ -24,6 +24,11 @@
 import java.util.LinkedList;
 import java.util.Map;
 
+/**
+ * @deprecated This class was inteded to be used by Gears. Since Gears was
+ * deprecated, so is this class.
+ */
+@Deprecated
 public final class UrlInterceptRegistry {
 
     private final static String LOGTAG = "intercept";
@@ -42,7 +47,10 @@
      * set the flag to control whether url intercept is enabled or disabled
      * 
      * @param disabled true to disable the cache
+     *
+     * @deprecated
      */
+    @Deprecated
     public static synchronized void setUrlInterceptDisabled(boolean disabled) {
         mDisabled = disabled;
     }
@@ -51,7 +59,10 @@
      * get the state of the url intercept, enabled or disabled
      * 
      * @return return if it is disabled
+     *
+     * @deprecated
      */
+    @Deprecated
     public static synchronized boolean urlInterceptDisabled() {
         return mDisabled;
     }
@@ -62,7 +73,10 @@
      *
      * @param handler The new UrlInterceptHandler object
      * @return true if the handler was not previously registered.
+     *
+     * @deprecated
      */
+    @Deprecated
     public static synchronized boolean registerHandler(
             UrlInterceptHandler handler) {
         if (!getHandlers().contains(handler)) {
@@ -78,7 +92,10 @@
      *
      * @param handler A previously registered UrlInterceptHandler.
      * @return true if the handler was found and removed from the list.
+     *
+     * @deprecated
      */
+    @Deprecated
     public static synchronized boolean unregisterHandler(
             UrlInterceptHandler handler) {
         return getHandlers().remove(handler);
@@ -89,8 +106,8 @@
      * UrlInterceptHandler interested, or null if none are.
      *
      * @return A CacheResult containing surrogate content.
-     * @Deprecated Use PluginData getPluginData( String url,
-     * Map<String, String> headers) instead.
+     *
+     * @deprecated
      */
     @Deprecated
     public static synchronized CacheResult getSurrogate(
@@ -115,7 +132,10 @@
      * intercepts are disabled.
      *
      * @return A PluginData instance containing surrogate content.
+     *
+     * @deprecated
      */
+    @Deprecated
     public static synchronized PluginData getPluginData(
             String url, Map<String, String> headers) {
         if (urlInterceptDisabled()) {
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index f22adb7..a1f2223 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -85,6 +85,10 @@
     // happens, the next time the user hits a key it is okay for the focus
     // pointer to not match the WebTextView's node pointer
     private boolean         mOkayForFocusNotToMatch;
+    // Whether or not a selection change was generated from webkit.  If it was,
+    // we do not need to pass the selection back to webkit.
+    private boolean         mFromWebKit;
+    private boolean         mGotTouchDown;
     // Array to store the final character added in onTextChanged, so that its
     // KeyEvents may be determined.
     private char[]          mCharacter = new char[1];
@@ -342,7 +346,7 @@
 
     @Override
     protected void onSelectionChanged(int selStart, int selEnd) {
-        if (mWebView != null) {
+        if (!mFromWebKit && mWebView != null) {
             if (DebugFlags.WEB_TEXT_VIEW) {
                 Log.v(LOGTAG, "onSelectionChanged selStart=" + selStart
                         + " selEnd=" + selEnd);
@@ -423,6 +427,7 @@
             mDragStartTime = event.getEventTime();
             mDragSent = false;
             mScrolled = false;
+            mGotTouchDown = true;
             break;
         case MotionEvent.ACTION_MOVE:
             Spannable buffer = getText();
@@ -456,14 +461,17 @@
         case MotionEvent.ACTION_CANCEL:
             if (!mScrolled) {
                 // If the page scrolled, or the TextView scrolled, we do not
-                // want to change the selection, and the long press has already
-                // been canceled, so there is no need to call into super.
-                super.onTouchEvent(event);
+                // want to change the selection
+                cancelLongPress();
+                if (mGotTouchDown && mWebView != null) {
+                    mWebView.touchUpOnTextField(event);
+                }
             }
             // Necessary for the WebView to reset its state
             if (mWebView != null && mDragSent) {
                 mWebView.onTouchEvent(event);
             }
+            mGotTouchDown = false;
             break;
         default:
             break;
@@ -686,6 +694,15 @@
     }
 
     /**
+     * Set the selection, and disable our onSelectionChanged action.
+     */
+    /* package */ void setSelectionFromWebKit(int start, int end) {
+        mFromWebKit = true;
+        Selection.setSelection((Spannable) getText(), start, end);
+        mFromWebKit = false;
+    }
+
+    /**
      * Set whether this is a single-line textfield or a multi-line textarea.
      * Textfields scroll horizontally, and do not handle the enter key.
      * Textareas behave oppositely.
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index cc7a228..be9daa5 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -306,9 +306,6 @@
     // Used by WebViewCore to create child views.
     /* package */ final ViewManager mViewManager;
 
-    // The list of loaded plugins.
-    private static PluginList sPluginList;
-
     /**
      * Position of the last touch event.
      */
@@ -469,7 +466,7 @@
     static final int UPDATE_TEXTFIELD_TEXT_MSG_ID       = 17;
     static final int MOVE_OUT_OF_PLUGIN                 = 19;
     static final int CLEAR_TEXT_ENTRY                   = 20;
-
+    static final int UPDATE_TEXT_SELECTION_MSG_ID       = 21;
     static final int UPDATE_CLIPBOARD                   = 22;
     static final int LONG_PRESS_CENTER                  = 23;
     static final int PREVENT_TOUCH_ID                   = 24;
@@ -499,7 +496,7 @@
         "18", //        = 18;
         "MOVE_OUT_OF_PLUGIN", //             = 19;
         "CLEAR_TEXT_ENTRY", //               = 20;
-        "21", //                             = 21;
+        "UPDATE_TEXT_SELECTION_MSG_ID", //   = 21;
         "UPDATE_CLIPBOARD", //               = 22;
         "LONG_PRESS_CENTER", //              = 23;
         "PREVENT_TOUCH_ID", //               = 24;
@@ -746,7 +743,7 @@
 
     private void updateZoomButtonsEnabled() {
         boolean canZoomIn = mActualScale < mMaxZoomScale;
-        boolean canZoomOut = mActualScale > mMinZoomScale;
+        boolean canZoomOut = mActualScale > mMinZoomScale && !mInZoomOverview;
         if (!canZoomIn && !canZoomOut) {
             // Hide the zoom in and out buttons, as well as the fit to page
             // button, if the page cannot zoom
@@ -2493,20 +2490,19 @@
    /**
     * Return the list of currently loaded plugins.
     * @return The list of currently loaded plugins.
+    *
+    * @deprecated This was used for Gears, which has been deprecated.
     */
+    @Deprecated
     public static synchronized PluginList getPluginList() {
-        if (sPluginList == null) {
-            sPluginList = new PluginList();
-        }
-        return sPluginList;
+        return null;
     }
 
    /**
-     * TODO: need to add @Deprecated
+    * @deprecated This was used for Gears, which has been deprecated.
     */
-    public void refreshPlugins(boolean reloadOpenPages) {
-        PluginManager.getInstance(mContext).refreshPlugins(reloadOpenPages);
-    }
+    @Deprecated
+    public void refreshPlugins(boolean reloadOpenPages) { }
 
     //-------------------------------------------------------------------------
     // Override View methods
@@ -3069,12 +3065,10 @@
      */
     /* package */ void deleteSelection(int start, int end) {
         mTextGeneration++;
-        WebViewCore.DeleteSelectionData data
-                = new WebViewCore.DeleteSelectionData();
-        data.mStart = start;
-        data.mEnd = end;
-        data.mTextGeneration = mTextGeneration;
-        mWebViewCore.sendMessage(EventHub.DELETE_SELECTION, data);
+        WebViewCore.TextSelectionData data
+                = new WebViewCore.TextSelectionData(start, end);
+        mWebViewCore.sendMessage(EventHub.DELETE_SELECTION, mTextGeneration, 0,
+                data);
     }
 
     /**
@@ -3896,7 +3890,7 @@
                         nativeHideCursor();
                     }
                     WebSettings settings = getSettings();
-                    if (settings.supportZoom() && !mInZoomOverview
+                    if (settings.supportZoom()
                             && settings.getBuiltInZoomControls()
                             && !mZoomButtonsController.isVisible()
                             && (canZoomScrollOut() ||
@@ -3965,7 +3959,7 @@
                     mUserScroll = true;
                 }
 
-                if (!getSettings().getBuiltInZoomControls() && !mInZoomOverview) {
+                if (!getSettings().getBuiltInZoomControls()) {
                     boolean showPlusMinus = mMinZoomScale < mMaxZoomScale;
                     boolean showMagnify = canZoomScrollOut();
                     if (mZoomControls != null && (showPlusMinus || showMagnify)) {
@@ -4550,9 +4544,17 @@
         // TODO: alternatively we can disallow this during draw history mode
         switchOutDrawHistory();
         // Center zooming to the center of the screen.
-        mZoomCenterX = getViewWidth() * .5f;
-        mZoomCenterY = getViewHeight() * .5f;
-        return zoomWithPreview(mActualScale * 1.25f);
+        if (mInZoomOverview) {
+            // if in overview mode, bring it back to normal mode
+            mLastTouchX = getViewWidth() * .5f;
+            mLastTouchY = getViewHeight() * .5f;
+            doDoubleTap();
+            return true;
+        } else {
+            mZoomCenterX = getViewWidth() * .5f;
+            mZoomCenterY = getViewHeight() * .5f;
+            return zoomWithPreview(mActualScale * 1.25f);
+        }
     }
 
     /**
@@ -4636,12 +4638,26 @@
         return result;
     }
 
+    /**
+     * Do a touch up from a WebTextView.  This will be handled by webkit to
+     * change the selection.
+     * @param event MotionEvent in the WebTextView's coordinates.
+     */
+    /*package*/ void touchUpOnTextField(MotionEvent event) {
+        if (!inEditingMode()) {
+            return;
+        }
+        int x = viewToContent((int) event.getX() + mWebTextView.getLeft());
+        int y = viewToContent((int) event.getY() + mWebTextView.getTop());
+        nativeTextInputMotionUp(x, y);
+    }
+
     /*package*/ void shortPressOnTextField() {
         if (inEditingMode()) {
             View v = mWebTextView;
             int x = viewToContent((v.getLeft() + v.getRight()) >> 1);
             int y = viewToContent((v.getTop() + v.getBottom()) >> 1);
-            nativeMotionUp(x, y, mNavSlop);
+            nativeTextInputMotionUp(x, y);
         }
     }
 
@@ -5089,6 +5105,16 @@
                         }
                     }
                     break;
+                case UPDATE_TEXT_SELECTION_MSG_ID:
+                    if (inEditingMode()
+                            && mWebTextView.isSameTextField(msg.arg1)
+                            && msg.arg2 == mTextGeneration) {
+                        WebViewCore.TextSelectionData tData
+                                = (WebViewCore.TextSelectionData) msg.obj;
+                        mWebTextView.setSelectionFromWebKit(tData.mStart,
+                                tData.mEnd);
+                    }
+                    break;
                 case MOVE_OUT_OF_PLUGIN:
                     if (nativePluginEatsNavKey()) {
                         navHandledKey(msg.arg1, 1, false, 0, true);
@@ -5453,10 +5479,9 @@
 
     // called by JNI
     private void sendMotionUp(int touchGeneration,
-            int frame, int node, int x, int y, int size) {
+            int frame, int node, int x, int y) {
         WebViewCore.TouchUpData touchUpData = new WebViewCore.TouchUpData();
         touchUpData.mMoveGeneration = touchGeneration;
-        touchUpData.mSize = size;
         touchUpData.mFrame = frame;
         touchUpData.mNode = node;
         touchUpData.mX = x;
@@ -5655,6 +5680,12 @@
     private native void     nativeSetHeightCanMeasure(boolean measure);
     // Returns a value corresponding to CachedFrame::ImeAction
     /* package */ native int  nativeTextFieldAction();
+    /**
+     * Perform a click on a currently focused text input.  Since it is already
+     * focused, there is no need to go through the nativeMotionUp code, which
+     * may change the Cursor.
+     */
+    private native void     nativeTextInputMotionUp(int x, int y);
     private native int      nativeTextGeneration();
     // Never call this version except by updateCachedTextfield(String) -
     // we always want to pass in our generation number.
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 05464b5..0720beb 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -440,8 +440,7 @@
     private native String nativeRetrieveHref(int framePtr, int nodePtr);
 
     private native void nativeTouchUp(int touchGeneration,
-            int framePtr, int nodePtr, int x, int y,
-            int size);
+            int framePtr, int nodePtr, int x, int y);
 
     private native boolean nativeHandleTouchEvent(int action, int x, int y);
 
@@ -611,12 +610,6 @@
         byte[] mPostData;
     }
 
-    static class DeleteSelectionData {
-        int mStart;
-        int mEnd;
-        int mTextGeneration;
-    }
-
     static class ReplaceTextData {
         String mReplace;
         int mNewStart;
@@ -624,13 +617,21 @@
         int mTextGeneration;
     }
 
+    static class TextSelectionData {
+        public TextSelectionData(int start, int end) {
+            mStart = start;
+            mEnd = end;
+        }
+        int mStart;
+        int mEnd;
+    }
+
     static class TouchUpData {
         int mMoveGeneration;
         int mFrame;
         int mNode;
         int mX;
         int mY;
-        int mSize;
     }
 
     static class TouchEventData {
@@ -1045,8 +1046,7 @@
                             TouchUpData touchUpData = (TouchUpData) msg.obj;
                             nativeTouchUp(touchUpData.mMoveGeneration,
                                     touchUpData.mFrame, touchUpData.mNode,
-                                    touchUpData.mX, touchUpData.mY,
-                                    touchUpData.mSize);
+                                    touchUpData.mX, touchUpData.mY);
                             break;
 
                         case TOUCH_EVENT: {
@@ -1116,11 +1116,10 @@
                             break;
 
                         case DELETE_SELECTION:
-                            DeleteSelectionData deleteSelectionData
-                                    = (DeleteSelectionData) msg.obj;
+                            TextSelectionData deleteSelectionData
+                                    = (TextSelectionData) msg.obj;
                             nativeDeleteSelection(deleteSelectionData.mStart,
-                                    deleteSelectionData.mEnd,
-                                    deleteSelectionData.mTextGeneration);
+                                    deleteSelectionData.mEnd, msg.arg1);
                             break;
 
                         case SET_SELECTION:
@@ -1946,6 +1945,16 @@
     }
 
     // called by JNI
+    private void updateTextSelection(int pointer, int start, int end,
+            int textGeneration) {
+        if (mWebView != null) {
+            Message.obtain(mWebView.mPrivateHandler,
+                WebView.UPDATE_TEXT_SELECTION_MSG_ID, pointer, textGeneration,
+                new TextSelectionData(start, end)).sendToTarget();
+        }
+    }
+
+    // called by JNI
     private void clearTextEntry() {
         if (mWebView == null) return;
         Message.obtain(mWebView.mPrivateHandler,
diff --git a/core/java/android/webkit/gears/AndroidGpsLocationProvider.java b/core/java/android/webkit/gears/AndroidGpsLocationProvider.java
deleted file mode 100644
index 3646042..0000000
--- a/core/java/android/webkit/gears/AndroidGpsLocationProvider.java
+++ /dev/null
@@ -1,156 +0,0 @@
-// Copyright 2008, The Android Open Source Project
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-//  1. Redistributions of source code must retain the above copyright notice,
-//     this list of conditions and the following disclaimer.
-//  2. Redistributions in binary form must reproduce the above copyright notice,
-//     this list of conditions and the following disclaimer in the documentation
-//     and/or other materials provided with the distribution.
-//  3. Neither the name of Google Inc. nor the names of its contributors may be
-//     used to endorse or promote products derived from this software without
-//     specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package android.webkit.gears;
-
-import android.content.Context;
-import android.location.Location;
-import android.location.LocationListener;
-import android.location.LocationManager;
-import android.location.LocationProvider;
-import android.os.Bundle;
-import android.util.Log;
-import android.webkit.WebView;
-
-/**
- * GPS provider implementation for Android.
- */
-public final class AndroidGpsLocationProvider implements LocationListener {
-  /**
-   * Logging tag
-   */
-  private static final String TAG = "Gears-J-GpsProvider";
-  /**
-   * Our location manager instance.
-   */
-  private LocationManager locationManager;
-  /**
-   * The native object ID.
-   */
-  private long nativeObject;
-
-  public AndroidGpsLocationProvider(WebView webview, long object) {
-    nativeObject = object;
-    locationManager = (LocationManager) webview.getContext().getSystemService(
-        Context.LOCATION_SERVICE);
-    if (locationManager == null) {
-      Log.e(TAG,
-          "AndroidGpsLocationProvider: could not get location manager.");
-      throw new NullPointerException(
-          "AndroidGpsLocationProvider: locationManager is null.");
-    }
-    // Register for location updates.
-    try {
-      locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
-          this);
-    } catch (IllegalArgumentException ex) {
-      Log.e(TAG,
-          "AndroidLocationGpsProvider: could not register for updates: " + ex);
-      throw ex;
-    } catch (SecurityException ex) {
-      Log.e(TAG,
-          "AndroidGpsLocationProvider: not allowed to register for update: "
-          + ex);
-      throw ex;
-    }
-  }
-
-  /**
-   * Called when the provider is no longer needed.
-   */
-  public void shutdown() {
-    locationManager.removeUpdates(this);
-    Log.i(TAG, "GPS provider closed.");
-  }
-
- /**
-  * Called when the location has changed.
-  * @param location The new location, as a Location object.
-  */
-  public void onLocationChanged(Location location) {
-    Log.i(TAG, "Location changed: " + location);
-    nativeLocationChanged(location, nativeObject);
-  }
-
-  /**
-   * Called when the provider status changes.
-   *
-   * @param provider the name of the location provider associated with this
-   * update.
-   * @param status {@link LocationProvider#OUT_OF_SERVICE} if the
-   * provider is out of service, and this is not expected to change in the
-   * near future; {@link LocationProvider#TEMPORARILY_UNAVAILABLE} if
-   * the provider is temporarily unavailable but is expected to be available
-   * shortly; and {@link LocationProvider#AVAILABLE} if the
-   * provider is currently available.
-   * @param extras an optional Bundle which will contain provider specific
-   * status variables (such as number of satellites).
-   */
-  public void onStatusChanged(String provider, int status, Bundle extras) {
-    Log.i(TAG, "Provider " + provider + " status changed to " + status);
-    if (status == LocationProvider.OUT_OF_SERVICE ||
-        status == LocationProvider.TEMPORARILY_UNAVAILABLE) {
-      nativeProviderError(false, nativeObject);
-    }
-  }
-
-  /**
-   * Called when the provider is enabled.
-   *
-   * @param provider the name of the location provider that is now enabled.
-   */
-  public void onProviderEnabled(String provider) {
-    Log.i(TAG, "Provider " + provider + " enabled.");
-    // No need to notify the native side. It's enough to start sending
-    // valid position fixes again.
-  }
-
-  /**
-   * Called when the provider is disabled.
-   *
-   * @param provider the name of the location provider that is now disabled.
-   */
-  public void onProviderDisabled(String provider) {
-    Log.i(TAG, "Provider " + provider + " disabled.");
-    nativeProviderError(true, nativeObject);
-  }
-
-  /**
-   * The native method called when a new location is available.
-   * @param location is the new Location instance to pass to the native side.
-   * @param nativeObject is a pointer to the corresponding
-   * AndroidGpsLocationProvider C++ instance.
-   */
-  private native void nativeLocationChanged(Location location, long object);
-
-  /**
-   * The native method called when there is a GPS provder error.
-   * @param isDisabled is true when the error signifies the fact that the GPS
-   * HW is disabled. For other errors, this param is always false.
-   * @param nativeObject is a pointer to the corresponding
-   * AndroidGpsLocationProvider C++ instance.
-   */
-  private native void nativeProviderError(boolean isDisabled, long object);
-}
diff --git a/core/java/android/webkit/gears/AndroidRadioDataProvider.java b/core/java/android/webkit/gears/AndroidRadioDataProvider.java
deleted file mode 100644
index 1384042..0000000
--- a/core/java/android/webkit/gears/AndroidRadioDataProvider.java
+++ /dev/null
@@ -1,260 +0,0 @@
-// Copyright 2008, The Android Open Source Project
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-//  1. Redistributions of source code must retain the above copyright notice,
-//     this list of conditions and the following disclaimer.
-//  2. Redistributions in binary form must reproduce the above copyright notice,
-//     this list of conditions and the following disclaimer in the documentation
-//     and/or other materials provided with the distribution.
-//  3. Neither the name of Google Inc. nor the names of its contributors may be
-//     used to endorse or promote products derived from this software without
-//     specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package android.webkit.gears;
-
-import android.content.Context;
-import android.telephony.CellLocation;
-import android.telephony.ServiceState;
-import android.telephony.SignalStrength;
-import android.telephony.gsm.GsmCellLocation;
-import android.telephony.PhoneStateListener;
-import android.telephony.TelephonyManager;
-import android.util.Log;
-import android.webkit.WebView;
-
-/**
- * Radio data provider implementation for Android.
- */
-public final class AndroidRadioDataProvider extends PhoneStateListener {
-
-  /** Logging tag */
-  private static final String TAG = "Gears-J-RadioProvider";
-
-  /** Network types */
-  private static final int RADIO_TYPE_UNKNOWN = 0;
-  private static final int RADIO_TYPE_GSM = 1;
-  private static final int RADIO_TYPE_WCDMA = 2;
-  private static final int RADIO_TYPE_CDMA = 3;
-  private static final int RADIO_TYPE_EVDO = 4;
-  private static final int RADIO_TYPE_1xRTT = 5;
-
-  /** Simple container for radio data */
-  public static final class RadioData {
-    public int cellId = -1;
-    public int locationAreaCode = -1;
-    // TODO: use new SignalStrength instead of asu
-    public int signalStrength = -1;
-    public int mobileCountryCode = -1;
-    public int mobileNetworkCode = -1;
-    public int homeMobileCountryCode = -1;
-    public int homeMobileNetworkCode = -1;
-    public int radioType = RADIO_TYPE_UNKNOWN;
-    public String carrierName;
-
-    /**
-     * Constructs radioData object from the given telephony data.
-     * @param telephonyManager contains the TelephonyManager instance.
-     * @param cellLocation contains information about the current GSM cell.
-     * @param signalStrength is the strength of the network signal.
-     * @param serviceState contains information about the network service.
-     * @return a new RadioData object populated with the currently
-     *         available network information or null if there isn't
-     *         enough information.
-     */
-    public static RadioData getInstance(TelephonyManager telephonyManager,
-        CellLocation cellLocation, int signalStrength,
-        ServiceState serviceState) {
-
-      if (!(cellLocation instanceof GsmCellLocation)) {
-        // This also covers the case when cellLocation is null.
-        // When that happens, we do not bother creating a
-        // RadioData instance.
-        return null;
-      }
-
-      RadioData radioData = new RadioData();
-      GsmCellLocation gsmCellLocation = (GsmCellLocation) cellLocation;
-
-      // Extract the cell id, LAC, and signal strength.
-      radioData.cellId = gsmCellLocation.getCid();
-      radioData.locationAreaCode = gsmCellLocation.getLac();
-      radioData.signalStrength = signalStrength;
-
-      // Extract the home MCC and home MNC.
-      String operator = telephonyManager.getSimOperator();
-      radioData.setMobileCodes(operator, true);
-
-      if (serviceState != null) {
-        // Extract the carrier name.
-        radioData.carrierName = serviceState.getOperatorAlphaLong();
-
-        // Extract the MCC and MNC.
-        operator = serviceState.getOperatorNumeric();
-        radioData.setMobileCodes(operator, false);
-      }
-
-      // Finally get the radio type.
-      //TODO We have to edit the parameter for getNetworkType regarding CDMA
-      int type = telephonyManager.getNetworkType();
-      if (type == TelephonyManager.NETWORK_TYPE_UMTS) {
-        radioData.radioType = RADIO_TYPE_WCDMA;
-      } else if (type == TelephonyManager.NETWORK_TYPE_GPRS
-                 || type == TelephonyManager.NETWORK_TYPE_EDGE) {
-        radioData.radioType = RADIO_TYPE_GSM;
-      } else if (type == TelephonyManager.NETWORK_TYPE_CDMA) {
-          radioData.radioType = RADIO_TYPE_CDMA;
-      } else if (type == TelephonyManager.NETWORK_TYPE_EVDO_0) {
-          radioData.radioType = RADIO_TYPE_EVDO;
-      } else if (type == TelephonyManager.NETWORK_TYPE_EVDO_A) {
-          radioData.radioType = RADIO_TYPE_EVDO;
-      } else if (type == TelephonyManager.NETWORK_TYPE_1xRTT) {
-          radioData.radioType = RADIO_TYPE_1xRTT;
-      }
-
-      // Print out what we got.
-      Log.i(TAG, "Got the following data:");
-      Log.i(TAG, "CellId: " + radioData.cellId);
-      Log.i(TAG, "LAC: " + radioData.locationAreaCode);
-      Log.i(TAG, "MNC: " + radioData.mobileNetworkCode);
-      Log.i(TAG, "MCC: " + radioData.mobileCountryCode);
-      Log.i(TAG, "home MNC: " + radioData.homeMobileNetworkCode);
-      Log.i(TAG, "home MCC: " + radioData.homeMobileCountryCode);
-      Log.i(TAG, "Signal strength: " + radioData.signalStrength);
-      Log.i(TAG, "Carrier: " + radioData.carrierName);
-      Log.i(TAG, "Network type: " + radioData.radioType);
-
-      return radioData;
-    }
-
-    private RadioData() {}
-
-    /**
-     * Parses a string containing a mobile country code and a mobile
-     * network code and sets the corresponding member variables.
-     * @param codes is the string to parse.
-     * @param homeValues flags whether the codes are for the home operator.
-     */
-    private void setMobileCodes(String codes, boolean homeValues) {
-      if (codes != null) {
-        try {
-          // The operator numeric format is 3 digit country code plus 2 or
-          // 3 digit network code.
-          int mcc = Integer.parseInt(codes.substring(0, 3));
-          int mnc = Integer.parseInt(codes.substring(3));
-          if (homeValues) {
-            homeMobileCountryCode = mcc;
-            homeMobileNetworkCode = mnc;
-          } else {
-            mobileCountryCode = mcc;
-            mobileNetworkCode = mnc;
-          }
-        } catch (IndexOutOfBoundsException ex) {
-          Log.e(
-              TAG,
-              "AndroidRadioDataProvider: Invalid operator numeric data: " + ex);
-        } catch (NumberFormatException ex) {
-          Log.e(
-              TAG,
-              "AndroidRadioDataProvider: Operator numeric format error: " + ex);
-        }
-      }
-    }
-  };
-
-  /** The native object ID */
-  private long nativeObject;
-
-  /** The last known cellLocation */
-  private CellLocation cellLocation = null;
-
-  /** The last known signal strength */
-  // TODO: use new SignalStrength instead of asu
-  private int signalStrength = -1;
-
-  /** The last known serviceState */
-  private ServiceState serviceState = null;
-
-  /**
-   * Our TelephonyManager instance.
-   */
-  private TelephonyManager telephonyManager;
-
-  /**
-   * Public constructor. Uses the webview to get the Context object.
-   */
-  public AndroidRadioDataProvider(WebView webview, long object) {
-    super();
-    nativeObject = object;
-    telephonyManager = (TelephonyManager) webview.getContext().getSystemService(
-        Context.TELEPHONY_SERVICE);
-    if (telephonyManager == null) {
-      Log.e(TAG,
-          "AndroidRadioDataProvider: could not get tepephony manager.");
-      throw new NullPointerException(
-          "AndroidRadioDataProvider: telephonyManager is null.");
-    }
-
-    // Register for cell id, signal strength and service state changed
-    // notifications.
-    telephonyManager.listen(this, PhoneStateListener.LISTEN_CELL_LOCATION
-        | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
-        | PhoneStateListener.LISTEN_SERVICE_STATE);
-  }
-
-  /**
-   * Should be called when the provider is no longer needed.
-   */
-  public void shutdown() {
-    telephonyManager.listen(this, PhoneStateListener.LISTEN_NONE);
-    Log.i(TAG, "AndroidRadioDataProvider shutdown.");
-  }
-
-  @Override
-  public void onServiceStateChanged(ServiceState state) {
-    serviceState = state;
-    notifyListeners();
-  }
-
-  @Override
-  public void onSignalStrengthsChanged(SignalStrength ss) {
-    int gsmSignalStrength = ss.getGsmSignalStrength();
-    signalStrength = (gsmSignalStrength == 99 ? -1 : gsmSignalStrength);
-    notifyListeners();
-  }
-
-  @Override
-  public void onCellLocationChanged(CellLocation location) {
-    cellLocation = location;
-    notifyListeners();
-  }
-
-  private void notifyListeners() {
-    RadioData radioData = RadioData.getInstance(telephonyManager, cellLocation,
-        signalStrength, serviceState);
-    if (radioData != null) {
-      onUpdateAvailable(radioData, nativeObject);
-    }
-  }
-
-  /**
-   * The native method called when new radio data is available.
-   * @param radioData is the RadioData instance to pass to the native side.
-   * @param nativeObject is a pointer to the corresponding
-   * AndroidRadioDataProvider C++ instance.
-   */
-  private static native void onUpdateAvailable(
-      RadioData radioData, long nativeObject);
-}
diff --git a/core/java/android/webkit/gears/AndroidWifiDataProvider.java b/core/java/android/webkit/gears/AndroidWifiDataProvider.java
deleted file mode 100644
index d2850b06..0000000
--- a/core/java/android/webkit/gears/AndroidWifiDataProvider.java
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright 2008, Google Inc.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-//  1. Redistributions of source code must retain the above copyright notice,
-//     this list of conditions and the following disclaimer.
-//  2. Redistributions in binary form must reproduce the above copyright notice,
-//     this list of conditions and the following disclaimer in the documentation
-//     and/or other materials provided with the distribution.
-//  3. Neither the name of Google Inc. nor the names of its contributors may be
-//     used to endorse or promote products derived from this software without
-//     specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package android.webkit.gears;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.net.wifi.ScanResult;
-import android.net.wifi.WifiManager;
-import android.os.Handler;
-import android.os.Looper;
-import android.util.Log;
-import android.webkit.WebView;
-import java.util.List;
-
-/**
- * WiFi data provider implementation for Android.
- * {@hide}
- */
-public final class AndroidWifiDataProvider extends BroadcastReceiver {
-  /**
-   * Logging tag
-   */
-  private static final String TAG = "Gears-J-WifiProvider";
-  /**
-   * Flag for guarding Log.v() calls.
-   * Set to true to enable extra debug logging.
-   */
-  private static final boolean LOGV_ENABLED = false;
-  /**
-   * Our Wifi manager instance.
-   */
-  private WifiManager mWifiManager;
-  /**
-   * The native object ID.
-   */
-  private long mNativeObject;
-  /**
-   * The Context instance.
-   */
-  private Context mContext;
-
-  /**
-   * Constructs a instance of this class and registers for wifi scan
-   * updates. Note that this constructor must be called on a Looper
-   * thread. Suitable threads can be created on the native side using
-   * the AndroidLooperThread C++ class.
-   */
-  public AndroidWifiDataProvider(WebView webview, long object) {
-    mNativeObject = object;
-    mContext = webview.getContext();
-    mWifiManager =
-        (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
-    if (mWifiManager == null) {
-      Log.e(TAG,
-          "AndroidWifiDataProvider: could not get location manager.");
-      throw new NullPointerException(
-          "AndroidWifiDataProvider: locationManager is null.");
-    }
-
-    // Create a Handler that identifies the message loop associated
-    // with the current thread. Note that it is not necessary to
-    // override handleMessage() at all since the Intent
-    // ReceiverDispatcher (see the ActivityThread class) only uses
-    // this handler to post a Runnable to this thread's loop.
-    Handler handler = new Handler(Looper.myLooper());
-
-    IntentFilter filter = new IntentFilter();
-    filter.addAction(mWifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
-    mContext.registerReceiver(this, filter, null, handler);
-
-    // Get the last scan results and pass them to the native side.
-    // We can't just invoke the callback here, so we queue a message
-    // to this thread's loop.
-    handler.post(new Runnable() {
-        public void run() {
-          onUpdateAvailable(mWifiManager.getScanResults(), mNativeObject);
-        }
-      });
-  }
-
-  /**
-   * Called when the provider is no longer needed.
-   */
-  public void shutdown() {
-    mContext.unregisterReceiver(this);
-    if (LOGV_ENABLED) {
-      Log.v(TAG, "Wifi provider closed.");
-    }
-  }
-
-  /**
-   * This method is called when the AndroidWifiDataProvider is receiving an
-   * Intent broadcast.
-   * @param context The Context in which the receiver is running.
-   * @param intent The Intent being received.
-   */
-  public void onReceive(Context context, Intent intent) {
-    if (intent.getAction().equals(
-            mWifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
-      if (LOGV_ENABLED) {
-        Log.v(TAG, "Wifi scan resulst available");
-      }
-      onUpdateAvailable(mWifiManager.getScanResults(), mNativeObject);
-    }
-  }
-
- /**
-   * The native method called when new wifi data is available.
-   * @param scanResults is a list of ScanResults  to pass to the native side.
-   * @param nativeObject is a pointer to the corresponding
-   * AndroidWifiDataProvider C++ instance.
-   */
-  private static native void onUpdateAvailable(
-      List<ScanResult> scanResults, long nativeObject);
-}
diff --git a/core/java/android/webkit/gears/ApacheHttpRequestAndroid.java b/core/java/android/webkit/gears/ApacheHttpRequestAndroid.java
deleted file mode 100644
index b3d7f69..0000000
--- a/core/java/android/webkit/gears/ApacheHttpRequestAndroid.java
+++ /dev/null
@@ -1,1129 +0,0 @@
-// Copyright 2008, The Android Open Source Project
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-//  1. Redistributions of source code must retain the above copyright notice,
-//     this list of conditions and the following disclaimer.
-//  2. Redistributions in binary form must reproduce the above copyright notice,
-//     this list of conditions and the following disclaimer in the documentation
-//     and/or other materials provided with the distribution.
-//  3. Neither the name of Google Inc. nor the names of its contributors may be
-//     used to endorse or promote products derived from this software without
-//     specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package android.webkit.gears;
-
-import android.net.http.Headers;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.util.Log;
-import android.webkit.CacheManager;
-import android.webkit.CacheManager.CacheResult;
-import android.webkit.CookieManager;
-
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.IOException;
-import java.lang.StringBuilder;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.Iterator;
-
-import org.apache.http.Header;
-import org.apache.http.HttpEntity;
-import org.apache.http.client.params.HttpClientParams;
-import org.apache.http.params.HttpParams;
-import org.apache.http.params.HttpConnectionParams;
-import org.apache.http.params.HttpProtocolParams;
-import org.apache.http.HttpResponse;
-import org.apache.http.entity.AbstractHttpEntity;
-import org.apache.http.client.*;
-import org.apache.http.client.methods.*;
-import org.apache.http.impl.client.AbstractHttpClient;
-import org.apache.http.impl.client.DefaultHttpClient;
-import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
-import org.apache.http.conn.ssl.StrictHostnameVerifier;
-import org.apache.http.util.CharArrayBuffer;
-
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-
-/**
- * Performs the underlying HTTP/HTTPS GET, POST, HEAD, PUT, DELETE requests.
- * <p> These are performed synchronously (blocking). The caller should
- * ensure that it is in a background thread if asynchronous behavior
- * is required. All data is pushed, so there is no need for JNI native
- * callbacks.
- * <p> This uses Apache's HttpClient framework to perform most
- * of the underlying network activity. The Android brower's cache,
- * android.webkit.CacheManager, is also used when caching is enabled,
- * and updated with new data. The android.webkit.CookieManager is also
- * queried and updated as necessary.
- * <p> The public interface is designed to be called by native code
- * through JNI, and to simplify coding none of the public methods will
- * surface a checked exception. Unchecked exceptions may still be
- * raised but only if the system is in an ill state, such as out of
- * memory.
- * <p> TODO: This isn't plumbed into LocalServer yet. Mutually
- * dependent on LocalServer - will attach the two together once both
- * are submitted.
- */
-public final class ApacheHttpRequestAndroid {
-    /** Debug logging tag. */
-    private static final String LOG_TAG = "Gears-J";
-    /** Flag for guarding Log.v() calls. */
-    private static final boolean LOGV_ENABLED = false;
-    /** HTTP response header line endings are CR-LF style. */
-    private static final String HTTP_LINE_ENDING = "\r\n";
-    /** Safe MIME type to use whenever it isn't specified. */
-    private static final String DEFAULT_MIME_TYPE = "text/plain";
-    /** Case-sensitive header keys */
-    public static final String KEY_CONTENT_LENGTH = "Content-Length";
-    public static final String KEY_EXPIRES = "Expires";
-    public static final String KEY_LAST_MODIFIED = "Last-Modified";
-    public static final String KEY_ETAG = "ETag";
-    public static final String KEY_LOCATION = "Location";
-    public static final String KEY_CONTENT_TYPE = "Content-Type";
-    /** Number of bytes to send and receive on the HTTP connection in
-     * one go. */
-    private static final int BUFFER_SIZE = 4096;
-
-    /** The first element of the String[] value in a headers map is the
-     * unmodified (case-sensitive) key. */
-    public static final int HEADERS_MAP_INDEX_KEY = 0;
-    /** The second element of the String[] value in a headers map is the
-     * associated value. */
-    public static final int HEADERS_MAP_INDEX_VALUE = 1;
-
-    /** Request headers, as key -> value map. */
-    // TODO: replace this design by a simpler one (the C++ side has to
-    // be modified too), where we do not store both the original header
-    // and the lowercase one.
-    private Map<String, String[]> mRequestHeaders =
-        new HashMap<String, String[]>();
-    /** Response headers, as a lowercase key -> value map. */
-    private Map<String, String[]> mResponseHeaders =
-        new HashMap<String, String[]>();
-    /** The URL used for createCacheResult() */
-    private String mCacheResultUrl;
-    /** CacheResult being saved into, if inserting a new cache entry. */
-    private CacheResult mCacheResult;
-    /** Initialized by initChildThread(). Used to target abort(). */
-    private Thread mBridgeThread;
-
-    /** Our HttpClient */
-    private AbstractHttpClient mClient;
-    /** The HttpMethod associated with this request */
-    private HttpRequestBase mMethod;
-    /** The complete response line e.g "HTTP/1.0 200 OK" */
-    private String mResponseLine;
-    /** HTTP body stream, setup after connection. */
-    private InputStream mBodyInputStream;
-
-    /** HTTP Response Entity */
-    private HttpResponse mResponse;
-
-    /** Post Entity, used to stream the request to the server */
-    private StreamEntity mPostEntity = null;
-    /** Content lenght, mandatory when using POST */
-    private long mContentLength;
-
-    /** The request executes in a parallel thread */
-    private Thread mHttpThread = null;
-    /** protect mHttpThread, if interrupt() is called concurrently */
-    private Lock mHttpThreadLock = new ReentrantLock();
-    /** Flag set to true when the request thread is joined */
-    private boolean mConnectionFinished = false;
-    /** Flag set to true by interrupt() and/or connection errors */
-    private boolean mConnectionFailed = false;
-    /** Lock protecting the access to mConnectionFailed */
-    private Lock mConnectionFailedLock = new ReentrantLock();
-
-    /** Lock on the loop in StreamEntity */
-    private Lock mStreamingReadyLock = new ReentrantLock();
-    /** Condition variable used to signal the loop is ready... */
-    private Condition mStreamingReady = mStreamingReadyLock.newCondition();
-
-    /** Used to pass around the block of data POSTed */
-    private Buffer mBuffer = new Buffer();
-    /** Used to signal that the block of data has been written */
-    private SignalConsumed mSignal = new SignalConsumed();
-
-    // inner classes
-
-    /**
-     * Implements the http request
-     */
-    class Connection implements Runnable {
-        public void run() {
-            boolean problem = false;
-            try {
-                if (LOGV_ENABLED) {
-                    Log.i(LOG_TAG, "REQUEST : " + mMethod.getRequestLine());
-                }
-                mResponse = mClient.execute(mMethod);
-                if (mResponse != null) {
-                    if (LOGV_ENABLED) {
-                        Log.i(LOG_TAG, "response (status line): "
-                              + mResponse.getStatusLine());
-                    }
-                    mResponseLine = "" + mResponse.getStatusLine();
-                } else {
-                    if (LOGV_ENABLED) {
-                        Log.i(LOG_TAG, "problem, response == null");
-                    }
-                    problem = true;
-                }
-            } catch (IOException e) {
-                Log.e(LOG_TAG, "Connection IO exception ", e);
-                problem = true;
-            } catch (RuntimeException e) {
-                Log.e(LOG_TAG, "Connection runtime exception ", e);
-                problem = true;
-            }
-
-            if (!problem) {
-                if (LOGV_ENABLED) {
-                    Log.i(LOG_TAG, "Request complete ("
-                          + mMethod.getRequestLine() + ")");
-                }
-            } else {
-                mConnectionFailedLock.lock();
-                mConnectionFailed = true;
-                mConnectionFailedLock.unlock();
-                if (LOGV_ENABLED) {
-                    Log.i(LOG_TAG, "Request FAILED ("
-                          + mMethod.getRequestLine() + ")");
-                }
-                // We abort the execution in order to shutdown and release
-                // the underlying connection
-                mMethod.abort();
-                if (mPostEntity != null) {
-                    // If there is a post entity, we need to wake it up from
-                    // a potential deadlock
-                    mPostEntity.signalOutputStream();
-                }
-            }
-        }
-    }
-
-    /**
-     * simple buffer class implementing a producer/consumer model
-     */
-    class Buffer {
-        private DataPacket mPacket;
-        private boolean mEmpty = true;
-        public synchronized void put(DataPacket packet) {
-            while (!mEmpty) {
-                try {
-                    wait();
-                } catch (InterruptedException e) {
-                    if (LOGV_ENABLED) {
-                        Log.i(LOG_TAG, "InterruptedException while putting " +
-                            "a DataPacket in the Buffer: " + e);
-                    }
-                }
-            }
-            mPacket = packet;
-            mEmpty = false;
-            notify();
-        }
-        public synchronized DataPacket get() {
-            while (mEmpty) {
-                try {
-                    wait();
-                } catch (InterruptedException e) {
-                    if (LOGV_ENABLED) {
-                      Log.i(LOG_TAG, "InterruptedException while getting " +
-                          "a DataPacket in the Buffer: " + e);
-                    }
-                }
-            }
-            mEmpty = true;
-            notify();
-            return mPacket;
-        }
-    }
-
-    /**
-     * utility class used to block until the packet is signaled as being
-     * consumed
-     */
-    class SignalConsumed {
-        private boolean mConsumed = false;
-        public synchronized void waitUntilPacketConsumed() {
-            while (!mConsumed) {
-                try {
-                    wait();
-                } catch (InterruptedException e) {
-                    if (LOGV_ENABLED) {
-                        Log.i(LOG_TAG, "InterruptedException while waiting " +
-                            "until a DataPacket is consumed: " + e);
-                    }
-                }
-            }
-            mConsumed = false;
-            notify();
-        }
-        public synchronized void packetConsumed() {
-            while (mConsumed) {
-                try {
-                    wait();
-                } catch (InterruptedException e) {
-                    if (LOGV_ENABLED) {
-                        Log.i(LOG_TAG, "InterruptedException while indicating "
-                              + "that the DataPacket has been consumed: " + e);
-                    }
-                }
-            }
-            mConsumed = true;
-            notify();
-        }
-    }
-
-    /**
-     * Utility class encapsulating a packet of data
-     */
-    class DataPacket {
-        private byte[] mContent;
-        private int mLength;
-        public DataPacket(byte[] content, int length) {
-            mContent = content;
-            mLength = length;
-        }
-        public byte[] getBytes() {
-            return mContent;
-        }
-        public int getLength() {
-            return mLength;
-        }
-    }
-
-    /**
-     * HttpEntity class to write the bytes received by the C++ thread
-     * on the connection outputstream, in a streaming way.
-     * This entity is executed in the request thread.
-     * The writeTo() method is automatically called by the
-     * HttpPost execution; upon reception, we loop while receiving
-     * the data packets from the main thread, until completion
-     * or error. When done, we flush the outputstream.
-     * The main thread (sendPostData()) also blocks until the
-     * outputstream is made available (or an error happens)
-     */
-    class StreamEntity implements HttpEntity {
-        private OutputStream mOutputStream;
-
-        // HttpEntity interface methods
-
-        public boolean isRepeatable() {
-            return false;
-        }
-
-        public boolean isChunked() {
-            return false;
-        }
-
-        public long getContentLength() {
-            return mContentLength;
-        }
-
-        public Header getContentType() {
-            return null;
-        }
-
-        public Header getContentEncoding() {
-            return null;
-        }
-
-        public InputStream getContent() throws IOException {
-            return null;
-        }
-
-        public void writeTo(final OutputStream out) throws IOException {
-            // We signal that the outputstream is available
-            mStreamingReadyLock.lock();
-            mOutputStream = out;
-            mStreamingReady.signal();
-            mStreamingReadyLock.unlock();
-
-            // We then loop waiting on messages to process.
-            boolean finished = false;
-            while (!finished) {
-                DataPacket packet = mBuffer.get();
-                if (packet == null) {
-                    finished = true;
-                } else {
-                    write(packet);
-                }
-                mSignal.packetConsumed();
-                mConnectionFailedLock.lock();
-                if (mConnectionFailed) {
-                    if (LOGV_ENABLED) {
-                        Log.i(LOG_TAG, "stopping loop on error");
-                    }
-                    finished = true;
-                }
-                mConnectionFailedLock.unlock();
-            }
-            if (LOGV_ENABLED) {
-                Log.i(LOG_TAG, "flushing the outputstream...");
-            }
-            mOutputStream.flush();
-        }
-
-        public boolean isStreaming() {
-            return true;
-        }
-
-        public void consumeContent() throws IOException {
-            // Nothing to release
-        }
-
-        // local methods
-
-        private void write(DataPacket packet) {
-            try {
-                if (mOutputStream == null) {
-                    if (LOGV_ENABLED) {
-                        Log.i(LOG_TAG, "NO OUTPUT STREAM !!!");
-                    }
-                    return;
-                }
-                mOutputStream.write(packet.getBytes(), 0, packet.getLength());
-                mOutputStream.flush();
-            } catch (IOException e) {
-                if (LOGV_ENABLED) {
-                    Log.i(LOG_TAG, "exc: " + e);
-                }
-                mConnectionFailedLock.lock();
-                mConnectionFailed = true;
-                mConnectionFailedLock.unlock();
-            }
-        }
-
-        public boolean isReady() {
-            mStreamingReadyLock.lock();
-            try {
-                if (mOutputStream == null) {
-                    mStreamingReady.await();
-                }
-            } catch (InterruptedException e) {
-                if (LOGV_ENABLED) {
-                    Log.i(LOG_TAG, "InterruptedException in "
-                          + "StreamEntity::isReady() : ", e);
-                }
-            } finally {
-                mStreamingReadyLock.unlock();
-            }
-            if (mOutputStream == null) {
-                return false;
-            }
-            return true;
-        }
-
-        public void signalOutputStream() {
-            mStreamingReadyLock.lock();
-            mStreamingReady.signal();
-            mStreamingReadyLock.unlock();
-        }
-    }
-
-    /**
-     * Initialize mBridgeThread using the TLS value of
-     * Thread.currentThread(). Called on start up of the native child
-     * thread.
-     */
-    public synchronized void initChildThread() {
-        mBridgeThread = Thread.currentThread();
-    }
-
-    public void setContentLength(long length) {
-        mContentLength = length;
-    }
-
-    /**
-     * Analagous to the native-side HttpRequest::open() function. This
-     * initializes an underlying HttpClient method, but does
-     * not go to the wire. On success, this enables a call to send() to
-     * initiate the transaction.
-     *
-     * @param method    The HTTP method, e.g GET or POST.
-     * @param url       The URL to open.
-     * @return          True on success with a complete HTTP response.
-     *                  False on failure.
-     */
-    public synchronized boolean open(String method, String url) {
-        if (LOGV_ENABLED) {
-            Log.i(LOG_TAG, "open " + method + " " + url);
-        }
-        // Create the client
-        if (mConnectionFailed) {
-            // interrupt() could have been called even before open()
-            return false;
-        }
-        mClient = new DefaultHttpClient();
-        mClient.setHttpRequestRetryHandler(
-            new DefaultHttpRequestRetryHandler(0, false));
-        mBodyInputStream = null;
-        mResponseLine = null;
-        mResponseHeaders = null;
-        mPostEntity = null;
-        mHttpThread = null;
-        mConnectionFailed = false;
-        mConnectionFinished = false;
-
-        // Create the method. We support everything that
-        // Apache HttpClient supports, apart from TRACE.
-        if ("GET".equalsIgnoreCase(method)) {
-            mMethod = new HttpGet(url);
-        } else if ("POST".equalsIgnoreCase(method)) {
-            mMethod = new HttpPost(url);
-            mPostEntity = new StreamEntity();
-            ((HttpPost)mMethod).setEntity(mPostEntity);
-        } else if ("HEAD".equalsIgnoreCase(method)) {
-            mMethod = new HttpHead(url);
-        } else if ("PUT".equalsIgnoreCase(method)) {
-            mMethod = new HttpPut(url);
-        } else if ("DELETE".equalsIgnoreCase(method)) {
-            mMethod = new HttpDelete(url);
-        } else {
-            if (LOGV_ENABLED) {
-                Log.i(LOG_TAG, "Method " + method + " not supported");
-            }
-            return false;
-        }
-        HttpParams params = mClient.getParams();
-        // We handle the redirections C++-side
-        HttpClientParams.setRedirecting(params, false);
-        HttpProtocolParams.setUseExpectContinue(params, false);
-        return true;
-    }
-
-    /**
-     * We use this to start the connection thread (doing the method execute).
-     * We usually always return true here, as the connection will run its
-     * course in the thread.
-     * We only return false if interrupted beforehand -- if a connection
-     * problem happens, we will thus fail in either sendPostData() or
-     * parseHeaders().
-     */
-    public synchronized boolean connectToRemote() {
-        boolean ret = false;
-        applyRequestHeaders();
-        mConnectionFailedLock.lock();
-        if (!mConnectionFailed) {
-            mHttpThread = new Thread(new Connection());
-            mHttpThread.start();
-        }
-        ret = mConnectionFailed;
-        mConnectionFailedLock.unlock();
-        return !ret;
-    }
-
-    /**
-     * Get the complete response line of the HTTP request. Only valid on
-     * completion of the transaction.
-     * @return The complete HTTP response line, e.g "HTTP/1.0 200 OK".
-     */
-    public synchronized String getResponseLine() {
-        return mResponseLine;
-    }
-
-    /**
-     * Wait for the request thread completion
-     * (unless already finished)
-     */
-    private void waitUntilConnectionFinished() {
-        if (LOGV_ENABLED) {
-            Log.i(LOG_TAG, "waitUntilConnectionFinished("
-                  + mConnectionFinished + ")");
-        }
-        if (!mConnectionFinished) {
-            if (mHttpThread != null) {
-                try {
-                    mHttpThread.join();
-                    mConnectionFinished = true;
-                    if (LOGV_ENABLED) {
-                        Log.i(LOG_TAG, "http thread joined");
-                    }
-                } catch (InterruptedException e) {
-                    if (LOGV_ENABLED) {
-                        Log.i(LOG_TAG, "interrupted: " + e);
-                    }
-                }
-            } else {
-                Log.e(LOG_TAG, ">>> Trying to join on mHttpThread " +
-                      "when it does not exist!");
-            }
-        }
-    }
-
-    // Headers handling
-
-    /**
-     * Receive all headers from the server and populate
-     * mResponseHeaders.
-     * @return True if headers are successfully received, False on
-     *         connection error.
-     */
-    public synchronized boolean parseHeaders() {
-        mConnectionFailedLock.lock();
-        if (mConnectionFailed) {
-            mConnectionFailedLock.unlock();
-            return false;
-        }
-        mConnectionFailedLock.unlock();
-        waitUntilConnectionFinished();
-        mResponseHeaders = new HashMap<String, String[]>();
-        if (mResponse == null)
-            return false;
-
-        Header[] headers = mResponse.getAllHeaders();
-        for (int i = 0; i < headers.length; i++) {
-            Header header = headers[i];
-            if (LOGV_ENABLED) {
-                Log.i(LOG_TAG, "header " + header.getName()
-                      + " -> " + header.getValue());
-            }
-            setResponseHeader(header.getName(), header.getValue());
-        }
-
-        return true;
-    }
-
-    /**
-     * Set a header to send with the HTTP request. Will not take effect
-     * on a transaction already in progress. The key is associated
-     * case-insensitive, but stored case-sensitive.
-     * @param name  The name of the header, e.g "Set-Cookie".
-     * @param value The value for this header, e.g "text/html".
-     */
-    public synchronized void setRequestHeader(String name, String value) {
-        String[] mapValue = { name, value };
-        if (LOGV_ENABLED) {
-            Log.i(LOG_TAG, "setRequestHeader: " + name + " => " + value);
-        }
-        if (name.equalsIgnoreCase(KEY_CONTENT_LENGTH)) {
-            setContentLength(Long.parseLong(value));
-        } else {
-            mRequestHeaders.put(name.toLowerCase(), mapValue);
-        }
-    }
-
-    /**
-     * Returns the value associated with the given request header.
-     * @param name The name of the request header, non-null, case-insensitive.
-     * @return The value associated with the request header, or null if
-     *         not set, or error.
-     */
-    public synchronized String getRequestHeader(String name) {
-        String[] value = mRequestHeaders.get(name.toLowerCase());
-        if (value != null) {
-            return value[HEADERS_MAP_INDEX_VALUE];
-        } else {
-            return null;
-        }
-    }
-
-    private void applyRequestHeaders() {
-        if (mMethod == null)
-            return;
-        Iterator<String[]> it = mRequestHeaders.values().iterator();
-        while (it.hasNext()) {
-            // Set the key case-sensitive.
-            String[] entry = it.next();
-            if (LOGV_ENABLED) {
-                Log.i(LOG_TAG, "apply header " + entry[HEADERS_MAP_INDEX_KEY] +
-                    " => " + entry[HEADERS_MAP_INDEX_VALUE]);
-            }
-            mMethod.setHeader(entry[HEADERS_MAP_INDEX_KEY],
-                                     entry[HEADERS_MAP_INDEX_VALUE]);
-        }
-    }
-
-    /**
-     * Returns the value associated with the given response header.
-     * @param name The name of the response header, non-null, case-insensitive.
-     * @return The value associated with the response header, or null if
-     *         not set or error.
-     */
-    public synchronized String getResponseHeader(String name) {
-        if (mResponseHeaders != null) {
-            String[] value = mResponseHeaders.get(name.toLowerCase());
-            if (value != null) {
-                return value[HEADERS_MAP_INDEX_VALUE];
-            } else {
-                return null;
-            }
-        } else {
-            if (LOGV_ENABLED) {
-                Log.i(LOG_TAG, "getResponseHeader() called but "
-                      + "response not received");
-            }
-            return null;
-        }
-    }
-
-    /**
-     * Return all response headers, separated by CR-LF line endings, and
-     * ending with a trailing blank line. This mimics the format of the
-     * raw response header up to but not including the body.
-     * @return A string containing the entire response header.
-     */
-    public synchronized String getAllResponseHeaders() {
-        if (mResponseHeaders == null) {
-            if (LOGV_ENABLED) {
-                Log.i(LOG_TAG, "getAllResponseHeaders() called but "
-                      + "response not received");
-            }
-            return null;
-        }
-        StringBuilder result = new StringBuilder();
-        Iterator<String[]> it = mResponseHeaders.values().iterator();
-        while (it.hasNext()) {
-            String[] entry = it.next();
-            // Output the "key: value" lines.
-            result.append(entry[HEADERS_MAP_INDEX_KEY]);
-            result.append(": ");
-            result.append(entry[HEADERS_MAP_INDEX_VALUE]);
-            result.append(HTTP_LINE_ENDING);
-        }
-        result.append(HTTP_LINE_ENDING);
-        return result.toString();
-    }
-
-
-    /**
-     * Set a response header and associated value. The key is associated
-     * case-insensitively, but stored case-sensitively.
-     * @param name  Case sensitive request header key.
-     * @param value The associated value.
-     */
-    private void setResponseHeader(String name, String value) {
-        if (LOGV_ENABLED) {
-            Log.i(LOG_TAG, "Set response header " + name + ": " + value);
-        }
-        String mapValue[] = { name, value };
-        mResponseHeaders.put(name.toLowerCase(), mapValue);
-    }
-
-    // Cookie handling
-
-    /**
-     * Get the cookie for the given URL.
-     * @param url The fully qualified URL.
-     * @return A string containing the cookie for the URL if it exists,
-     *         or null if not.
-     */
-    public static String getCookieForUrl(String url) {
-        // Get the cookie for this URL, set as a header
-        return CookieManager.getInstance().getCookie(url);
-    }
-
-    /**
-     * Set the cookie for the given URL.
-     * @param url    The fully qualified URL.
-     * @param cookie The new cookie value.
-     * @return A string containing the cookie for the URL if it exists,
-     *         or null if not.
-     */
-    public static void setCookieForUrl(String url, String cookie) {
-        // Get the cookie for this URL, set as a header
-        CookieManager.getInstance().setCookie(url, cookie);
-    }
-
-    // Cache handling
-
-    /**
-     * Perform a request using LocalServer if possible. Initializes
-     * class members so that receive() will obtain data from the stream
-     * provided by the response.
-     * @param url The fully qualified URL to try in LocalServer.
-     * @return True if the url was found and is now setup to receive.
-     *         False if not found, with no side-effect.
-     */
-    public synchronized boolean useLocalServerResult(String url) {
-        UrlInterceptHandlerGears handler =
-            UrlInterceptHandlerGears.getInstance();
-        if (handler == null) {
-            return false;
-        }
-        UrlInterceptHandlerGears.ServiceResponse serviceResponse =
-            handler.getServiceResponse(url, mRequestHeaders);
-        if (serviceResponse == null) {
-            if (LOGV_ENABLED) {
-                Log.i(LOG_TAG, "No response in LocalServer");
-            }
-            return false;
-        }
-        // LocalServer will handle this URL. Initialize stream and
-        // response.
-        mBodyInputStream = serviceResponse.getInputStream();
-        mResponseLine = serviceResponse.getStatusLine();
-        mResponseHeaders = serviceResponse.getResponseHeaders();
-        if (LOGV_ENABLED) {
-            Log.i(LOG_TAG, "Got response from LocalServer: " + mResponseLine);
-        }
-        return true;
-    }
-
-    /**
-     * Perform a request using the cache result if present. Initializes
-     * class members so that receive() will obtain data from the cache.
-     * @param url The fully qualified URL to try in the cache.
-     * @return True is the url was found and is now setup to receive
-     *         from cache. False if not found, with no side-effect.
-     */
-    public synchronized boolean useCacheResult(String url) {
-        // Try the browser's cache. CacheManager wants a Map<String, String>.
-        Map<String, String> cacheRequestHeaders = new HashMap<String, String>();
-        Iterator<Map.Entry<String, String[]>> it =
-            mRequestHeaders.entrySet().iterator();
-        while (it.hasNext()) {
-            Map.Entry<String, String[]> entry = it.next();
-            cacheRequestHeaders.put(
-                entry.getKey(),
-                entry.getValue()[HEADERS_MAP_INDEX_VALUE]);
-        }
-        CacheResult mCacheResult =
-            CacheManager.getCacheFile(url, cacheRequestHeaders);
-        if (mCacheResult == null) {
-            if (LOGV_ENABLED) {
-                Log.i(LOG_TAG, "No CacheResult for " + url);
-            }
-            return false;
-        }
-        if (LOGV_ENABLED) {
-            Log.i(LOG_TAG, "Got CacheResult from browser cache");
-        }
-        // Check for expiry. -1 is "never", otherwise milliseconds since 1970.
-        // Can be compared to System.currentTimeMillis().
-        long expires = mCacheResult.getExpires();
-        if (expires >= 0 && System.currentTimeMillis() >= expires) {
-            if (LOGV_ENABLED) {
-                Log.i(LOG_TAG, "CacheResult expired "
-                    + (System.currentTimeMillis() - expires)
-                    + " milliseconds ago");
-            }
-            // Cache hit has expired. Do not return it.
-            return false;
-        }
-        // Setup the mBodyInputStream to come from the cache.
-        mBodyInputStream = mCacheResult.getInputStream();
-        if (mBodyInputStream == null) {
-            // Cache result may have gone away.
-            if (LOGV_ENABLED) {
-                Log.i(LOG_TAG, "No mBodyInputStream for CacheResult " + url);
-            }
-            return false;
-        }
-        // Cache hit. Parse headers.
-        synthesizeHeadersFromCacheResult(mCacheResult);
-        return true;
-    }
-
-    /**
-     * Take the limited set of headers in a CacheResult and synthesize
-     * response headers.
-     * @param cacheResult A CacheResult to populate mResponseHeaders with.
-     */
-    private void synthesizeHeadersFromCacheResult(CacheResult cacheResult) {
-        int statusCode = cacheResult.getHttpStatusCode();
-        // The status message is informal, so we can greatly simplify it.
-        String statusMessage;
-        if (statusCode >= 200 && statusCode < 300) {
-            statusMessage = "OK";
-        } else if (statusCode >= 300 && statusCode < 400) {
-            statusMessage = "MOVED";
-        } else {
-            statusMessage = "UNAVAILABLE";
-        }
-        // Synthesize the response line.
-        mResponseLine = "HTTP/1.1 " + statusCode + " " + statusMessage;
-        if (LOGV_ENABLED) {
-            Log.i(LOG_TAG, "Synthesized " + mResponseLine);
-        }
-        // Synthesize the returned headers from cache.
-        mResponseHeaders = new HashMap<String, String[]>();
-        String contentLength = Long.toString(cacheResult.getContentLength());
-        setResponseHeader(KEY_CONTENT_LENGTH, contentLength);
-        String expires = cacheResult.getExpiresString();
-        if (expires != null) {
-            setResponseHeader(KEY_EXPIRES, expires);
-        }
-        String lastModified = cacheResult.getLastModified();
-        if (lastModified != null) {
-            // Last modification time of the page. Passed end-to-end, but
-            // not used by us.
-            setResponseHeader(KEY_LAST_MODIFIED, lastModified);
-        }
-        String eTag = cacheResult.getETag();
-        if (eTag != null) {
-            // Entity tag. A kind of GUID to identify identical resources.
-            setResponseHeader(KEY_ETAG, eTag);
-        }
-        String location = cacheResult.getLocation();
-        if (location != null) {
-            // If valid, refers to the location of a redirect.
-            setResponseHeader(KEY_LOCATION, location);
-        }
-        String mimeType = cacheResult.getMimeType();
-        if (mimeType == null) {
-            // Use a safe default MIME type when none is
-            // specified. "text/plain" is safe to render in the browser
-            // window (even if large) and won't be intepreted as anything
-            // that would cause execution.
-            mimeType = DEFAULT_MIME_TYPE;
-        }
-        String encoding = cacheResult.getEncoding();
-        // Encoding may not be specified. No default.
-        String contentType = mimeType;
-        if (encoding != null) {
-            if (encoding.length() > 0) {
-                contentType += "; charset=" + encoding;
-            }
-        }
-        setResponseHeader(KEY_CONTENT_TYPE, contentType);
-    }
-
-    /**
-     * Create a CacheResult for this URL. This enables the repsonse body
-     * to be sent in calls to appendCacheResult().
-     * @param url          The fully qualified URL to add to the cache.
-     * @param responseCode The response code returned for the request, e.g 200.
-     * @param mimeType     The MIME type of the body, e.g "text/plain".
-     * @param encoding     The encoding, e.g "utf-8". Use "" for unknown.
-     */
-    public synchronized boolean createCacheResult(
-        String url, int responseCode, String mimeType, String encoding) {
-        if (LOGV_ENABLED) {
-            Log.i(LOG_TAG, "Making cache entry for " + url);
-        }
-        // Take the headers and parse them into a format needed by
-        // CacheManager.
-        Headers cacheHeaders = new Headers();
-        Iterator<Map.Entry<String, String[]>> it =
-            mResponseHeaders.entrySet().iterator();
-        while (it.hasNext()) {
-            Map.Entry<String, String[]> entry = it.next();
-            // Headers.parseHeader() expects lowercase keys.
-            String keyValue = entry.getKey() + ": "
-                + entry.getValue()[HEADERS_MAP_INDEX_VALUE];
-            CharArrayBuffer buffer = new CharArrayBuffer(keyValue.length());
-            buffer.append(keyValue);
-            // Parse it into the header container.
-            cacheHeaders.parseHeader(buffer);
-        }
-        mCacheResult = CacheManager.createCacheFile(
-            url, responseCode, cacheHeaders, mimeType, true);
-        if (mCacheResult != null) {
-            if (LOGV_ENABLED) {
-                Log.i(LOG_TAG, "Saving into cache");
-            }
-            mCacheResult.setEncoding(encoding);
-            mCacheResultUrl = url;
-            return true;
-        } else {
-            if (LOGV_ENABLED) {
-                Log.i(LOG_TAG, "Couldn't create mCacheResult");
-            }
-            return false;
-        }
-    }
-
-    /**
-     * Add data from the response body to the CacheResult created with
-     * createCacheResult().
-     * @param data  A byte array of the next sequential bytes in the
-     *              response body.
-     * @param bytes The number of bytes to write from the start of
-     *              the array.
-     * @return True if all bytes successfully written, false on failure.
-     */
-    public synchronized boolean appendCacheResult(byte[] data, int bytes) {
-        if (mCacheResult == null) {
-            if (LOGV_ENABLED) {
-                Log.i(LOG_TAG, "appendCacheResult() called without a "
-                      + "CacheResult initialized");
-            }
-            return false;
-        }
-        try {
-            mCacheResult.getOutputStream().write(data, 0, bytes);
-        } catch (IOException ex) {
-            if (LOGV_ENABLED) {
-                Log.i(LOG_TAG, "Got IOException writing cache data: " + ex);
-            }
-            return false;
-        }
-        return true;
-    }
-
-    /**
-     * Save the completed CacheResult into the CacheManager. This must
-     * have been created first with createCacheResult().
-     * @return Returns true if the entry has been successfully saved.
-     */
-    public synchronized boolean saveCacheResult() {
-        if (mCacheResult == null || mCacheResultUrl == null) {
-            if (LOGV_ENABLED) {
-                Log.i(LOG_TAG, "Tried to save cache result but "
-                      + "createCacheResult not called");
-            }
-            return false;
-        }
-
-        if (LOGV_ENABLED) {
-            Log.i(LOG_TAG, "Saving cache result");
-        }
-        CacheManager.saveCacheFile(mCacheResultUrl, mCacheResult);
-        mCacheResult = null;
-        mCacheResultUrl = null;
-        return true;
-    }
-
-    /**
-     * Called by the main thread to interrupt the child thread.
-     * We do not set mConnectionFailed here as we still need the
-     * ability to receive a null packet for sendPostData().
-     */
-    public synchronized void abort() {
-        if (LOGV_ENABLED) {
-            Log.i(LOG_TAG, "ABORT CALLED");
-        }
-        if (mMethod != null) {
-            mMethod.abort();
-        }
-    }
-
-   /**
-     * Interrupt a blocking IO operation and wait for the
-     * thread to complete.
-     */
-    public synchronized void interrupt() {
-        if (LOGV_ENABLED) {
-            Log.i(LOG_TAG, "INTERRUPT CALLED");
-        }
-        mConnectionFailedLock.lock();
-        mConnectionFailed = true;
-        mConnectionFailedLock.unlock();
-        if (mMethod != null) {
-            mMethod.abort();
-        }
-        if (mHttpThread != null) {
-            waitUntilConnectionFinished();
-        }
-    }
-
-    /**
-     * Receive the next sequential bytes of the response body after
-     * successful connection. This will receive up to the size of the
-     * provided byte array. If there is no body, this will return 0
-     * bytes on the first call after connection.
-     * @param  buf A pre-allocated byte array to receive data into.
-     * @return The number of bytes from the start of the array which
-     *         have been filled, 0 on EOF, or negative on error.
-     */
-    public synchronized int receive(byte[] buf) {
-        if (mBodyInputStream == null) {
-            // If this is the first call, setup the InputStream. This may
-            // fail if there were headers, but no body returned by the
-            // server.
-            try {
-                if (mResponse != null) {
-                    HttpEntity entity = mResponse.getEntity();
-                    mBodyInputStream = entity.getContent();
-                }
-            } catch (IOException inputException) {
-                if (LOGV_ENABLED) {
-                    Log.i(LOG_TAG, "Failed to connect InputStream: "
-                          + inputException);
-                }
-                // Not unexpected. For example, 404 response return headers,
-                // and sometimes a body with a detailed error.
-            }
-            if (mBodyInputStream == null) {
-                // No error stream either. Treat as a 0 byte response.
-                if (LOGV_ENABLED) {
-                    Log.i(LOG_TAG, "No InputStream");
-                }
-                return 0; // EOF.
-            }
-        }
-        int ret;
-        try {
-            int got = mBodyInputStream.read(buf);
-            if (got > 0) {
-                // Got some bytes, not EOF.
-                ret = got;
-            } else {
-                // EOF.
-                mBodyInputStream.close();
-                ret = 0;
-            }
-        } catch (IOException e) {
-            // An abort() interrupts us by calling close() on our stream.
-            if (LOGV_ENABLED) {
-                Log.i(LOG_TAG, "Got IOException in mBodyInputStream.read(): ", e);
-            }
-            ret = -1;
-        }
-        return ret;
-    }
-
-    /**
-     * For POST method requests, send a stream of data provided by the
-     * native side in repeated callbacks.
-     * We put the data in mBuffer, and wait until it is consumed
-     * by the StreamEntity in the request thread.
-     * @param data  A byte array containing the data to sent, or null
-     *              if indicating EOF.
-     * @param bytes The number of bytes from the start of the array to
-     *              send, or 0 if indicating EOF.
-     * @return True if all bytes were successfully sent, false on error.
-     */
-    public boolean sendPostData(byte[] data, int bytes) {
-        mConnectionFailedLock.lock();
-        if (mConnectionFailed) {
-            mConnectionFailedLock.unlock();
-            return false;
-        }
-        mConnectionFailedLock.unlock();
-        if (mPostEntity == null) return false;
-
-        // We block until the outputstream is available
-        // (or in case of connection error)
-        if (!mPostEntity.isReady()) return false;
-
-        if (data == null && bytes == 0) {
-            mBuffer.put(null);
-        } else {
-            mBuffer.put(new DataPacket(data, bytes));
-        }
-        mSignal.waitUntilPacketConsumed();
-
-        mConnectionFailedLock.lock();
-        if (mConnectionFailed) {
-            Log.e(LOG_TAG, "failure");
-            mConnectionFailedLock.unlock();
-            return false;
-        }
-        mConnectionFailedLock.unlock();
-        return true;
-    }
-
-}
diff --git a/core/java/android/webkit/gears/DesktopAndroid.java b/core/java/android/webkit/gears/DesktopAndroid.java
deleted file mode 100644
index a7a144b..0000000
--- a/core/java/android/webkit/gears/DesktopAndroid.java
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright 2008 The Android Open Source Project
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-//  1. Redistributions of source code must retain the above copyright notice,
-//     this list of conditions and the following disclaimer.
-//  2. Redistributions in binary form must reproduce the above copyright notice,
-//     this list of conditions and the following disclaimer in the documentation
-//     and/or other materials provided with the distribution.
-//  3. Neither the name of Google Inc. nor the names of its contributors may be
-//     used to endorse or promote products derived from this software without
-//     specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package android.webkit.gears;
-
-import android.content.Context;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.net.Uri;
-import android.provider.Browser;
-import android.util.Log;
-import android.webkit.WebView;
-
-/**
- * Utility class to create a shortcut on Android
- */
-public class DesktopAndroid {
-
-  private static final String TAG = "Gears-J-Desktop";
-  private static final String EXTRA_SHORTCUT_DUPLICATE = "duplicate";
-  private static final String ACTION_INSTALL_SHORTCUT =
-      "com.android.launcher.action.INSTALL_SHORTCUT";
-
-  // Android now enforces a 64x64 limit for the icon
-  private static int MAX_WIDTH = 64;
-  private static int MAX_HEIGHT = 64;
-
-  /**
-   * Small utility function returning a Bitmap object.
-   *
-   * @param path the icon path
-   */
-  private static Bitmap getBitmap(String path) {
-    return BitmapFactory.decodeFile(path);
-  }
-
-  /**
-   * Create a shortcut for a webpage.
-   *
-   * <p>To set a shortcut on Android, we use the ACTION_INSTALL_SHORTCUT
-   * from the default Home application. We only have to create an Intent
-   * containing extra parameters specifying the shortcut.
-   * <p>Note: the shortcut mechanism is not system wide and depends on the
-   * Home application; if phone carriers decide to rewrite a Home application
-   * that does not accept this Intent, no shortcut will be added.
-   *
-   * @param webview the webview we are called from
-   * @param title the shortcut's title
-   * @param url the shortcut's url
-   * @param imagePath the local path of the shortcut's icon
-   */
-  public static void setShortcut(WebView webview, String title,
-        String url, String imagePath) {
-    Context context = webview.getContext();
-
-    Intent viewWebPage = new Intent(Intent.ACTION_VIEW);
-    viewWebPage.setData(Uri.parse(url));
-    long urlHash = url.hashCode();
-    long uniqueId = (urlHash << 32) | viewWebPage.hashCode();
-    viewWebPage.putExtra(Browser.EXTRA_APPLICATION_ID,
-            Long.toString(uniqueId));
-
-    Intent intent = new Intent(ACTION_INSTALL_SHORTCUT);
-    intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, viewWebPage);
-    intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, title);
-
-    // We disallow the creation of duplicate shortcuts (i.e. same
-    // url, same title, but different screen position).
-    intent.putExtra(EXTRA_SHORTCUT_DUPLICATE, false);
-
-    Bitmap bmp = getBitmap(imagePath);
-    if (bmp != null) {
-      if ((bmp.getWidth() > MAX_WIDTH) ||
-          (bmp.getHeight() > MAX_HEIGHT)) {
-        Bitmap scaledBitmap = Bitmap.createScaledBitmap(bmp,
-            MAX_WIDTH, MAX_HEIGHT, true);
-        intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, scaledBitmap);
-      } else {
-        intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, bmp);
-      }
-    } else {
-      // This should not happen as we just downloaded the icon
-      Log.e(TAG, "icon file <" + imagePath + "> not found");
-    }
-
-    context.sendBroadcast(intent);
-  }
-
-}
diff --git a/core/java/android/webkit/gears/NativeDialog.java b/core/java/android/webkit/gears/NativeDialog.java
deleted file mode 100644
index 9e2b375..0000000
--- a/core/java/android/webkit/gears/NativeDialog.java
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright 2008 The Android Open Source Project
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-//  1. Redistributions of source code must retain the above copyright notice,
-//     this list of conditions and the following disclaimer.
-//  2. Redistributions in binary form must reproduce the above copyright notice,
-//     this list of conditions and the following disclaimer in the documentation
-//     and/or other materials provided with the distribution.
-//  3. Neither the name of Google Inc. nor the names of its contributors may be
-//     used to endorse or promote products derived from this software without
-//     specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package android.webkit.gears;
-
-import android.content.ActivityNotFoundException;
-import android.content.Context;
-import android.content.Intent;
-import android.util.Log;
-
-import java.io.File;
-import java.lang.InterruptedException;
-import java.util.concurrent.locks.Condition;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-
-/**
- * Utility class to call a modal native dialog on Android
- * The dialog itself is an Activity defined in the Browser.
- * @hide
- */
-public class NativeDialog {
-
-  private static final String TAG = "Gears-J-NativeDialog";
-
-  private final String DIALOG_PACKAGE = "com.android.browser";
-  private final String DIALOG_CLASS = DIALOG_PACKAGE + ".GearsNativeDialog";
-
-  private static Lock mLock = new ReentrantLock();
-  private static Condition mDialogFinished = mLock.newCondition();
-  private static String mResults = null;
-
-  private static boolean mAsynchronousDialog;
-
-  /**
-   * Utility function to build the intent calling the
-   * dialog activity
-   */
-  private Intent createIntent(String type, String arguments) {
-    Intent intent = new Intent();
-    intent.setClassName(DIALOG_PACKAGE, DIALOG_CLASS);
-    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-    intent.putExtra("dialogArguments", arguments);
-    intent.putExtra("dialogType", type);
-    return intent;
-  }
-
-  /**
-   * Opens a native dialog synchronously and waits for its completion.
-   *
-   * The dialog is an activity (GearsNativeDialog) provided by the Browser
-   * that we call via startActivity(). Contrary to a normal activity though,
-   * we need to block until it returns. To do so, we define a static lock
-   * object in this class, which GearsNativeDialog can unlock once done
-   */
-  public String showDialog(Context context, String file,
-      String arguments) {
-
-    try {
-      mAsynchronousDialog = false;
-      mLock.lock();
-      File path = new File(file);
-      String fileName = path.getName();
-      String type = fileName.substring(0, fileName.indexOf(".html"));
-      Intent intent = createIntent(type, arguments);
-
-      mResults = null;
-      context.startActivity(intent);
-      mDialogFinished.await();
-    } catch (InterruptedException e) {
-      Log.e(TAG, "exception e: " + e);
-    } catch (ActivityNotFoundException e) {
-      Log.e(TAG, "exception e: " + e);
-    } finally {
-      mLock.unlock();
-    }
-
-    return mResults;
-  }
-
-  /**
-   * Opens a native dialog asynchronously
-   *
-   * The dialog is an activity (GearsNativeDialog) provided by the
-   * Browser.
-   */
-  public void showAsyncDialog(Context context, String type,
-                           String arguments) {
-    mAsynchronousDialog = true;
-    Intent intent = createIntent(type, arguments);
-    context.startActivity(intent);
-  }
-
-  /**
-   * Static method that GearsNativeDialog calls to unlock us
-   */
-  public static void signalFinishedDialog() {
-    if (!mAsynchronousDialog) {
-      mLock.lock();
-      mDialogFinished.signal();
-      mLock.unlock();
-    } else {
-      // we call the native callback
-      closeAsynchronousDialog(mResults);
-    }
-  }
-
-  /**
-   * Static method that GearsNativeDialog calls to set the
-   * dialog's result
-   */
-  public static void closeDialog(String res) {
-    mResults = res;
-  }
-
-  /**
-   * Native callback method
-   */
-  private native static void closeAsynchronousDialog(String res);
-}
diff --git a/core/java/android/webkit/gears/PluginSettings.java b/core/java/android/webkit/gears/PluginSettings.java
deleted file mode 100644
index 2d0cc13..0000000
--- a/core/java/android/webkit/gears/PluginSettings.java
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2008 The Android Open Source Project
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-//  1. Redistributions of source code must retain the above copyright notice,
-//     this list of conditions and the following disclaimer.
-//  2. Redistributions in binary form must reproduce the above copyright notice,
-//     this list of conditions and the following disclaimer in the documentation
-//     and/or other materials provided with the distribution.
-//  3. Neither the name of Google Inc. nor the names of its contributors may be
-//     used to endorse or promote products derived from this software without
-//     specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package android.webkit.gears;
-
-import android.content.Context;
-import android.util.Log;
-import android.webkit.Plugin;
-import android.webkit.Plugin.PreferencesClickHandler;
-
-/**
- * Simple bridge class intercepting the click in the
- * browser plugin list and calling the Gears settings
- * dialog.
- */
-public class PluginSettings {
-
-  private static final String TAG = "Gears-J-PluginSettings";
-  private Context mContext;
-
-  public PluginSettings(Plugin plugin) {
-    plugin.setClickHandler(new ClickHandler());
-  }
-
-  /**
-   * We do not call the dialog synchronously here as the main
-   * message loop would be blocked, so we call it via a secondary thread.
-   */
-  private class ClickHandler implements PreferencesClickHandler {
-    public void handleClickEvent(Context context) {
-      mContext = context.getApplicationContext();
-      Thread startDialog = new Thread(new StartDialog(context));
-      startDialog.start();
-    }
-  }
-
-  /**
-   * Simple wrapper class to call the gears native method in
-   * a separate thread (the native code will then instanciate a NativeDialog
-   * object which will start the GearsNativeDialog activity defined in
-   * the Browser).
-   */
-  private class StartDialog implements Runnable {
-    Context mContext;
-
-    public StartDialog(Context context) {
-      mContext = context;
-    }
-
-    public void run() {
-      runSettingsDialog(mContext);
-    }
-  }
-
-  private static native void runSettingsDialog(Context c);
-
-}
diff --git a/core/java/android/webkit/gears/UrlInterceptHandlerGears.java b/core/java/android/webkit/gears/UrlInterceptHandlerGears.java
deleted file mode 100644
index 43104bf..0000000
--- a/core/java/android/webkit/gears/UrlInterceptHandlerGears.java
+++ /dev/null
@@ -1,417 +0,0 @@
-// Copyright 2008, The Android Open Source Project
-//
-// Redistribution and use in source and binary forms, with or without 
-// modification, are permitted provided that the following conditions are met:
-//
-//  1. Redistributions of source code must retain the above copyright notice, 
-//     this list of conditions and the following disclaimer.
-//  2. Redistributions in binary form must reproduce the above copyright notice,
-//     this list of conditions and the following disclaimer in the documentation
-//     and/or other materials provided with the distribution.
-//  3. Neither the name of Google Inc. nor the names of its contributors may be
-//     used to endorse or promote products derived from this software without
-//     specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package android.webkit.gears;
-
-import android.util.Log;
-import android.webkit.CacheManager.CacheResult;
-import android.webkit.Plugin;
-import android.webkit.PluginData;
-import android.webkit.UrlInterceptRegistry;
-import android.webkit.UrlInterceptHandler;
-import android.webkit.WebView;
-
-import org.apache.http.util.CharArrayBuffer;
-
-import java.io.*;
-import java.util.*;
-
-/**
- * Services requests to handle URLs coming from the browser or
- * HttpRequestAndroid. This registers itself with the
- * UrlInterceptRegister in Android so we get a chance to service all
- * URLs passing through the browser before anything else.
- */
-public class UrlInterceptHandlerGears implements UrlInterceptHandler {
-  /** Singleton instance. */
-  private static UrlInterceptHandlerGears instance;
-  /** Debug logging tag. */
-  private static final String LOG_TAG = "Gears-J";
-  /** Buffer size for reading/writing streams. */
-  private static final int BUFFER_SIZE = 4096;
-  /** Enable/disable all logging in this class. */
-  private static boolean logEnabled = false;
-  /** The unmodified (case-sensitive) key in the headers map is the
-   * same index as used by HttpRequestAndroid. */
-  public static final int HEADERS_MAP_INDEX_KEY =
-      ApacheHttpRequestAndroid.HEADERS_MAP_INDEX_KEY;
-  /** The associated value in the headers map is the same index as
-   * used by HttpRequestAndroid. */
-  public static final int HEADERS_MAP_INDEX_VALUE =
-      ApacheHttpRequestAndroid.HEADERS_MAP_INDEX_VALUE;
-
-  /**
-   * Object passed to the native side, containing information about
-   * the URL to service.
-   */
-  public static class ServiceRequest {
-    // The URL being requested.
-    private String url;
-    // Request headers. Map of lowercase key to [ unmodified key, value ].
-    private Map<String, String[]> requestHeaders;
-
-    /**
-     * Initialize members on construction.
-     * @param url The URL being requested.
-     * @param requestHeaders Headers associated with the request,
-     *                       or null if none.
-     *                       Map of lowercase key to [ unmodified key, value ].
-     */
-    public ServiceRequest(String url, Map<String, String[]> requestHeaders) {
-      this.url = url;
-      this.requestHeaders = requestHeaders;
-    }
-
-    /**
-     * Returns the URL being requested.
-     * @return The URL being requested.
-     */
-    public String getUrl() {
-      return url;
-    }
-
-    /**
-     * Get the value associated with a request header key, if any.
-     * @param header The key to find, case insensitive.
-     * @return The value associated with this header, or null if not found.
-     */
-    public String getRequestHeader(String header) {
-      if (requestHeaders != null) {
-        String[] value = requestHeaders.get(header.toLowerCase());
-        if (value != null) {
-          return value[HEADERS_MAP_INDEX_VALUE];
-        } else {
-          return null;
-        }
-      } else {
-        return null;
-      }
-    }
-  }
-
-  /**
-   * Object returned by the native side, containing information needed
-   * to pass the entire response back to the browser or
-   * HttpRequestAndroid. Works from either an in-memory array or a
-   * file on disk.
-   */
-  public class ServiceResponse {
-    // The response status code, e.g 200.
-    private int statusCode;
-    // The full status line, e.g "HTTP/1.1 200 OK".
-    private String statusLine;
-    // All headers associated with the response. Map of lowercase key
-    // to [ unmodified key, value ].
-    private Map<String, String[]> responseHeaders =
-        new HashMap<String, String[]>();
-    // The MIME type, e.g "text/html".
-    private String mimeType;
-    // The encoding, e.g "utf-8", or null if none.
-    private String encoding;
-    // The stream which contains the body when read().
-    private InputStream inputStream;
-    // The length of the content body.
-    private long contentLength;
-
-    /**
-     * Initialize members using an in-memory array to return the body.
-     * @param statusCode The response status code, e.g 200.
-     * @param statusLine The full status line, e.g "HTTP/1.1 200 OK".
-     * @param mimeType The MIME type, e.g "text/html".
-     * @param encoding Encoding, e.g "utf-8" or null if none.
-     * @param body The response body as a byte array, non-empty.
-     */
-    void setResultArray(
-        int statusCode,
-        String statusLine,
-        String mimeType,
-        String encoding,
-        byte[] body) {
-      this.statusCode = statusCode;
-      this.statusLine = statusLine;
-      this.mimeType = mimeType;
-      this.encoding = encoding;
-      // Setup a stream to read out of the byte array.
-      this.contentLength = body.length;
-      this.inputStream = new ByteArrayInputStream(body);
-    }
-    
-    /**
-     * Initialize members using a file on disk to return the body.
-     * @param statusCode The response status code, e.g 200.
-     * @param statusLine The full status line, e.g "HTTP/1.1 200 OK".
-     * @param mimeType The MIME type, e.g "text/html".
-     * @param encoding Encoding, e.g "utf-8" or null if none.
-     * @param path Full path to the file containing the body.
-     * @return True if the file is successfully setup to stream,
-     *         false on error such as file not found.
-     */
-    boolean setResultFile(
-        int statusCode,
-        String statusLine,
-        String mimeType,
-        String encoding,
-        String path) {
-      this.statusCode = statusCode;
-      this.statusLine = statusLine;
-      this.mimeType = mimeType;
-      this.encoding = encoding;
-      try {
-        // Setup a stream to read out of a file on disk.
-        File file = new File(path);
-        this.contentLength = file.length();
-        this.inputStream = new FileInputStream(file);
-        return true;
-      } catch (java.io.FileNotFoundException ex) {
-        log("File not found: " + path);
-        return false;
-      }
-    }
-    
-    /**
-     * Set a response header, adding its settings to the header members.
-     * @param key   The case sensitive key for the response header,
-     *              e.g "Set-Cookie".
-     * @param value The value associated with this key, e.g "cookie1234".
-     */
-    public void setResponseHeader(String key, String value) {
-      // The map value contains the unmodified key (not lowercase).
-      String[] mapValue = { key, value };
-      responseHeaders.put(key.toLowerCase(), mapValue);
-    }
-
-    /**
-     * Return the "Content-Type" header possibly supplied by a
-     * previous setResponseHeader().
-     * @return The "Content-Type" value, or null if not present.
-     */
-    public String getContentType() {
-      // The map keys are lowercase.
-      String[] value = responseHeaders.get("content-type");
-      if (value != null) {
-        return value[HEADERS_MAP_INDEX_VALUE];
-      } else {
-        return null;
-      }
-    }
-
-    /**
-     * Returns the HTTP status code for the response, supplied in
-     * setResultArray() or setResultFile().
-     * @return The HTTP statue code, e.g 200.
-     */
-    public int getStatusCode() {
-      return statusCode;
-    }
-    
-    /**
-     * Returns the full HTTP status line for the response, supplied in
-     * setResultArray() or setResultFile().
-     * @return The HTTP statue line, e.g "HTTP/1.1 200 OK".
-     */
-    public String getStatusLine() {
-      return statusLine;
-    }
-    
-    /**
-     * Get all response headers supplied in calls in
-     * setResponseHeader().
-     * @return A Map<String, String[]> containing all headers.
-     */
-    public Map<String, String[]> getResponseHeaders() {
-      return responseHeaders;
-    }
-
-    /**
-     * Returns the MIME type for the response, supplied in
-     * setResultArray() or setResultFile().
-     * @return The MIME type, e.g "text/html".
-     */
-    public String getMimeType() {
-      return mimeType;
-    }
-    
-    /**
-     * Returns the encoding for the response, supplied in
-     * setResultArray() or setResultFile(), or null if none.
-     * @return The encoding, e.g "utf-8", or null if none.
-     */
-    public String getEncoding() {
-      return encoding;
-    }
-
-    /**
-     * Returns the InputStream setup by setResultArray() or
-     * setResultFile() to allow reading data either from memory or
-     * disk.
-     * @return The InputStream containing the response body.
-     */
-    public InputStream getInputStream() {
-      return inputStream;
-    }
-
-    /**
-     * @return The length of the response body.
-     */
-    public long getContentLength() {
-      return contentLength;
-    }
-  }
-
-  /**
-   * Construct and initialize the singleton instance.
-   */
-  public UrlInterceptHandlerGears() {
-    if (instance != null) {
-      Log.e(LOG_TAG, "UrlInterceptHandlerGears singleton already constructed");
-      throw new RuntimeException();
-    }
-    instance = this;
-  }
-
-  /**
-   * Turn on/off logging in this class.
-   * @param on Logging enable state.
-   */
-  public static void enableLogging(boolean on) {
-    logEnabled = on;
-  }
-
-  /**
-   * Get the singleton instance.
-   * @return The singleton instance.
-   */
-  public static UrlInterceptHandlerGears getInstance() {
-    return instance;
-  }
-
-  /**
-   * Register the singleton instance with the browser's interception
-   * mechanism.
-   */
-  public synchronized void register() {
-    UrlInterceptRegistry.registerHandler(this);
-  }
-
-  /**
-   * Unregister the singleton instance from the browser's interception
-   * mechanism.
-   */
-  public synchronized void unregister() {
-    UrlInterceptRegistry.unregisterHandler(this);
-  }
-
-    /**
-     * Given an URL, returns the CacheResult which contains the
-     * surrogate response for the request, or null if the handler is
-     * not interested.
-     *
-     * @param url URL string.
-     * @param headers The headers associated with the request. May be null.
-     * @return The CacheResult containing the surrogate response.
-     * @Deprecated Use PluginData getPluginData(String url,
-     * Map<String, String> headers); instead
-     */
-    @Deprecated
-    public CacheResult service(String url, Map<String, String> headers) {
-      throw new UnsupportedOperationException("unimplemented");
-    }
-
-  /**
-   * Given an URL, returns a PluginData instance which contains the
-   * response for the request. This implements the UrlInterceptHandler
-   * interface.
-   *
-   * @param url The fully qualified URL being requested.
-   * @param requestHeaders The request headers for this URL.
-   * @return a PluginData object.
-   */
-  public PluginData getPluginData(String url, Map<String, String> requestHeaders) {
-    // Thankfully the browser does call us with case-sensitive
-    // headers. We just need to map it case-insensitive.
-    Map<String, String[]> lowercaseRequestHeaders =
-        new HashMap<String, String[]>();
-    Iterator<Map.Entry<String, String>> requestHeadersIt =
-        requestHeaders.entrySet().iterator();
-    while (requestHeadersIt.hasNext()) {
-      Map.Entry<String, String> entry = requestHeadersIt.next();
-      String key = entry.getKey();
-      String mapValue[] = { key, entry.getValue() };
-      lowercaseRequestHeaders.put(key.toLowerCase(), mapValue);
-    }
-    ServiceResponse response = getServiceResponse(url, lowercaseRequestHeaders);
-    if (response == null) {
-      // No result for this URL.
-      return null;
-    }
-    return new PluginData(response.getInputStream(),
-                          response.getContentLength(),
-                          response.getResponseHeaders(),
-                          response.getStatusCode());
-  }
-
-  /**
-   * Given an URL, returns a CacheResult and headers which contain the
-   * response for the request.
-   *
-   * @param url             The fully qualified URL being requested.
-   * @param requestHeaders  The request headers for this URL.
-   * @return If a response can be crafted, a ServiceResponse is
-   *         created which contains all response headers and an InputStream
-   *         attached to the body. If there is no response, null is returned.
-   */
-  public ServiceResponse getServiceResponse(String url,
-      Map<String, String[]> requestHeaders) {
-    if (!url.startsWith("http://") && !url.startsWith("https://")) {
-      // Don't know how to service non-HTTP URLs
-      return null;
-    }
-    // Call the native handler to craft a response for this URL.
-    return nativeService(new ServiceRequest(url, requestHeaders));
-  }
-
-  /**
-   * Convenience debug function. Calls the Android logging
-   * mechanism. logEnabled is not a constant, so if the string
-   * evaluation is potentially expensive, the caller also needs to
-   * check it.
-   * @param str String to log to the Android console.
-   */
-  private void log(String str) {
-    if (logEnabled) {
-      Log.i(LOG_TAG, str);
-    }
-  }
-
-  /**
-   * Native method which handles the bulk of the request in LocalServer.
-   * @param request A ServiceRequest object containing information about
-   *                the request.
-   * @return If serviced, a ServiceResponse object containing all the
-   *         information to provide a response for the URL, or null
-   *         if no response available for this URL.
-   */
-  private native static ServiceResponse nativeService(ServiceRequest request);
-}
diff --git a/core/java/android/webkit/gears/VersionExtractor.java b/core/java/android/webkit/gears/VersionExtractor.java
deleted file mode 100644
index 172dacb..0000000
--- a/core/java/android/webkit/gears/VersionExtractor.java
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright 2008, The Android Open Source Project
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-//  1. Redistributions of source code must retain the above copyright notice,
-//     this list of conditions and the following disclaimer.
-//  2. Redistributions in binary form must reproduce the above copyright notice,
-//     this list of conditions and the following disclaimer in the documentation
-//     and/or other materials provided with the distribution.
-//  3. Neither the name of Google Inc. nor the names of its contributors may be
-//     used to endorse or promote products derived from this software without
-//     specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package android.webkit.gears;
-
-import android.util.Log;
-import java.io.IOException;
-import java.io.StringReader;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.FactoryConfigurationError;
-import javax.xml.parsers.ParserConfigurationException;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.w3c.dom.Document;
-import org.w3c.dom.DOMException;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-/**
- * A class that can extract the Gears version and upgrade URL from an
- * xml document.
- */
-public final class VersionExtractor {
-
-  /**
-   * Logging tag
-   */
-  private static final String TAG = "Gears-J-VersionExtractor";
-  /**
-   * XML element names.
-   */
-  private static final String VERSION = "em:version";
-  private static final String URL = "em:updateLink";
-
-  /**
-   * Parses the input xml string and invokes the native
-   * setVersionAndUrl method.
-   * @param xml is the XML string to parse.
-   * @return true if the extraction is successful and false otherwise.
-   */
-  public static boolean extract(String xml, long nativeObject) {
-    try {
-      // Build the builders.
-      DocumentBuilderFactory factory =  DocumentBuilderFactory.newInstance();
-      factory.setNamespaceAware(false);
-      DocumentBuilder builder = factory.newDocumentBuilder();
-
-      // Create the document.
-      Document doc = builder.parse(new InputSource(new StringReader(xml)));
-
-      // Look for the version and url elements and get their text
-      // contents.
-      String version = extractText(doc, VERSION);
-      String url = extractText(doc, URL);
-
-      // If we have both, let the native side know.
-      if (version != null && url != null) {
-        setVersionAndUrl(version, url, nativeObject);
-        return true;
-      }
-
-      return false;
-
-    } catch (FactoryConfigurationError ex) {
-      Log.e(TAG, "Could not create the DocumentBuilderFactory " + ex);
-    } catch (ParserConfigurationException ex) {
-      Log.e(TAG, "Could not create the DocumentBuilder " + ex);
-    } catch (SAXException ex) {
-      Log.e(TAG, "Could not parse the xml " + ex);
-    } catch (IOException ex) {
-      Log.e(TAG, "Could not read the xml " + ex);
-    }
-
-    return false;
-  }
-
- /**
-   * Extracts the text content of the first element with the given name.
-   * @param doc is the Document where the element is searched for.
-   * @param elementName is name of the element to searched for.
-   * @return the text content of the element or null if no such
-   *         element is found.
-   */
-  private static String extractText(Document doc, String elementName) {
-    String text = null;
-    NodeList node_list = doc.getElementsByTagName(elementName);
-
-    if (node_list.getLength() > 0) {
-      // We are only interested in the first node. Normally there
-      // should not be more than one anyway.
-      Node  node = node_list.item(0);
-
-      // Iterate through the text children.
-      NodeList child_list = node.getChildNodes();
-
-      try {
-        for (int i = 0; i < child_list.getLength(); ++i) {
-          Node child = child_list.item(i);
-          if (child.getNodeType() == Node.TEXT_NODE) {
-            if (text == null) {
-              text = new String();
-            }
-            text += child.getNodeValue();
-          }
-        }
-      } catch (DOMException ex) {
-        Log.e(TAG, "getNodeValue() failed " + ex);
-      }
-    }
-
-    if (text != null) {
-      text = text.trim();
-    }
-
-    return text;
-  }
-
-  /**
-   * Native method used to send the version and url back to the C++
-   * side.
-   */
-  private static native void setVersionAndUrl(
-      String version, String url, long nativeObject);
-}
diff --git a/core/java/android/webkit/gears/ZipInflater.java b/core/java/android/webkit/gears/ZipInflater.java
deleted file mode 100644
index f6b6be5..0000000
--- a/core/java/android/webkit/gears/ZipInflater.java
+++ /dev/null
@@ -1,200 +0,0 @@
-// Copyright 2008, The Android Open Source Project
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-//  1. Redistributions of source code must retain the above copyright notice,
-//     this list of conditions and the following disclaimer.
-//  2. Redistributions in binary form must reproduce the above copyright notice,
-//     this list of conditions and the following disclaimer in the documentation
-//     and/or other materials provided with the distribution.
-//  3. Neither the name of Google Inc. nor the names of its contributors may be
-//     used to endorse or promote products derived from this software without
-//     specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-package android.webkit.gears;
-
-import android.os.StatFs;
-import android.util.Log;
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.zip.CRC32;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-import java.util.zip.ZipInputStream;
-
-
-/**
- * A class that can inflate a zip archive.
- */
-public final class ZipInflater {
-  /**
-   * Logging tag
-   */
-  private static final String TAG = "Gears-J-ZipInflater";
-
-  /**
-   * The size of the buffer used to read from the archive.
-   */
-  private static final int BUFFER_SIZE_BYTES = 32 * 1024;  // 32 KB.
-  /**
-   * The path navigation component (i.e. "../").
-   */
-  private static final String PATH_NAVIGATION_COMPONENT = ".." + File.separator;
-  /**
-   * The root of the data partition.
-   */
-  private static final String DATA_PARTITION_ROOT = "/data";
-
-  /**
-   * We need two be able to store two versions of gears in parallel:
-   * - the zipped version
-   * - the unzipped version, which will be loaded next time the browser is started.
-   * We are conservative and do not attempt to unpack unless there enough free
-   * space on the device to store 4 times the new Gears size.
-   */
-  private static final long SIZE_MULTIPLIER = 4;
-
-  /**
-   * Unzips the archive with the given name.
-   * @param filename is the name of the zip to inflate.
-   * @param path is the path where the zip should be unpacked. It must contain
-   *             a trailing separator, or the extraction will fail.
-   * @return true if the extraction is successful and false otherwise.
-   */
-  public static boolean inflate(String filename, String path) {
-    Log.i(TAG, "Extracting " + filename + " to " + path);
-
-    // Check that the path ends with a separator.
-    if (!path.endsWith(File.separator)) {
-      Log.e(TAG, "Path missing trailing separator: " + path);
-      return false;
-    }
-
-    boolean result = false;
-
-    // Use a ZipFile to get an enumeration of the entries and
-    // calculate the overall uncompressed size of the archive. Also
-    // check for existing files or directories that have the same
-    // name as the entries in the archive. Also check for invalid
-    // entry names (e.g names that attempt to navigate to the
-    // parent directory).
-    ZipInputStream zipStream = null;
-    long uncompressedSize = 0;
-    try {
-      ZipFile zipFile = new ZipFile(filename);
-      try {
-        Enumeration entries = zipFile.entries();
-        while (entries.hasMoreElements()) {
-          ZipEntry entry = (ZipEntry) entries.nextElement();
-          uncompressedSize += entry.getSize();
-          // Check against entry names that may attempt to navigate
-          // out of the destination directory.
-          if (entry.getName().indexOf(PATH_NAVIGATION_COMPONENT) >= 0) {
-            throw new IOException("Illegal entry name: " + entry.getName());
-          }
-
-          // Check against entries with the same name as pre-existing files or
-          // directories.
-          File file = new File(path + entry.getName());
-          if (file.exists()) {
-            // A file or directory with the same name already exist.
-            // This must not happen, so we treat this as an error.
-            throw new IOException(
-                "A file or directory with the same name already exists.");
-          }
-        }
-      } finally {
-        zipFile.close();
-      }
-
-      Log.i(TAG, "Determined uncompressed size: " + uncompressedSize);
-      // Check we have enough space to unpack this archive.
-      if (freeSpace() <= uncompressedSize * SIZE_MULTIPLIER) {
-        throw new IOException("Not enough space to unpack this archive.");
-      }
-
-      zipStream = new ZipInputStream(
-          new BufferedInputStream(new FileInputStream(filename)));
-      ZipEntry entry;
-      int counter;
-      byte buffer[] = new byte[BUFFER_SIZE_BYTES];
-
-      // Iterate through the entries and write each of them to a file.
-      while ((entry = zipStream.getNextEntry()) != null) {
-        File file = new File(path + entry.getName());
-        if (entry.isDirectory()) {
-          // If the entry denotes a directory, we need to create a
-          // directory with the same name.
-          file.mkdirs();
-        } else {
-          CRC32 checksum = new CRC32();
-          BufferedOutputStream output = new BufferedOutputStream(
-              new FileOutputStream(file),
-              BUFFER_SIZE_BYTES);
-          try {
-            // Read the entry and write it to the file.
-            while ((counter = zipStream.read(buffer, 0, BUFFER_SIZE_BYTES)) !=
-                -1) {
-              output.write(buffer, 0, counter);
-              checksum.update(buffer, 0, counter);
-            }
-            output.flush();
-          } finally {
-            output.close();
-          }
-
-          if (checksum.getValue() != entry.getCrc()) {
-            throw new IOException(
-                "Integrity check failed for: " + entry.getName());
-          }
-        }
-        zipStream.closeEntry();
-      }
-
-      result = true;
-
-    } catch (FileNotFoundException ex) {
-      Log.e(TAG, "The zip file could not be found. " + ex);
-    } catch (IOException ex) {
-      Log.e(TAG, "Could not read or write an entry. " + ex);
-    } catch(IllegalArgumentException ex) {
-      Log.e(TAG, "Could not create the BufferedOutputStream. " + ex);
-    } finally {
-      if (zipStream != null) {
-        try {
-          zipStream.close();
-        } catch (IOException ex) {
-          // Ignored.
-        }
-      }
-      // Discard any exceptions and return the result to the native side.
-      return result;
-    }
-  }
-
-  private static final long freeSpace() {
-    StatFs data_partition =  new StatFs(DATA_PARTITION_ROOT);
-    long freeSpace = data_partition.getAvailableBlocks() *
-        data_partition.getBlockSize();
-    Log.i(TAG, "Free space on the data partition: " + freeSpace);
-    return freeSpace;
-  }
-}
diff --git a/core/java/android/webkit/gears/package.html b/core/java/android/webkit/gears/package.html
deleted file mode 100644
index db6f78b..0000000
--- a/core/java/android/webkit/gears/package.html
+++ /dev/null
@@ -1,3 +0,0 @@
-<body>
-{@hide}
-</body>
\ No newline at end of file
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index a9822f8..6cc794b 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -59,7 +59,7 @@
      * Note: this is orthogonal to {@link #mBaselineAligned}, which is concerned
      * with whether the children of this layout are baseline aligned.
      */
-    private int mBaselineAlignedChildIndex = 0;
+    private int mBaselineAlignedChildIndex = -1;
 
     /**
      * The additional offset to the child's baseline.
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 2c9e71e..b179a13 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -190,10 +190,12 @@
 
         mBehavior = a.getInt(R.styleable.ProgressBar_indeterminateBehavior, mBehavior);
 
-        final int resID = a.getResourceId(com.android.internal.R.styleable.ProgressBar_interpolator, -1);
+        final int resID = a.getResourceId(
+                com.android.internal.R.styleable.ProgressBar_interpolator, 
+                android.R.anim.linear_interpolator); // default to linear interpolator
         if (resID > 0) {
             setInterpolator(context, resID);
-        }
+        } 
 
         setMax(a.getInt(R.styleable.ProgressBar_max, mMax));
 
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 591f9bb..e0a268e 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -327,6 +327,7 @@
         mText = "";
 
         mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
+        mTextPaint.density = getResources().getDisplayMetrics().density;
         // If we get the paint from the skin, we should set it to left, since
         // the layout always wants it to be left.
         // mTextPaint.setTextAlign(Paint.Align.LEFT);
diff --git a/core/java/com/android/internal/os/HandlerCaller.java b/core/java/com/android/internal/os/HandlerCaller.java
index 2ab9e09..e4c473d 100644
--- a/core/java/com/android/internal/os/HandlerCaller.java
+++ b/core/java/com/android/internal/os/HandlerCaller.java
@@ -93,6 +93,10 @@
         mH.sendMessage(msg);
     }
     
+    public boolean hasMessages(int what) {
+        return mH.hasMessages(what);
+    }
+    
     public void sendMessage(Message msg) {
         mH.sendMessage(msg);
     }
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 989286e..a2d3cd8 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -310,6 +310,15 @@
                         } else {
                             missingClasses += " " + line;
                         }
+                    } catch (Throwable t) {
+                        Log.e(TAG, "Error preloading " + line + ".", t);
+                        if (t instanceof Error) {
+                            throw (Error) t;
+                        }
+                        if (t instanceof RuntimeException) {
+                            throw (RuntimeException) t;
+                        }
+                        throw new RuntimeException(t);
                     }
                 }
 
diff --git a/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java b/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
index 6d50840..7266ee3 100644
--- a/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
+++ b/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
@@ -21,6 +21,7 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.service.wallpaper.WallpaperService;
+import android.util.Log;
 import android.view.SurfaceHolder;
 import android.content.Context;
 import android.content.IntentFilter;
@@ -63,12 +64,23 @@
 
     class DrawableEngine extends Engine {
         private final Object mLock = new Object();
+        private final Rect mBounds = new Rect();
         Drawable mBackground;
+        int mXOffset;
+        int mYOffset;
 
         @Override
         public void onCreate(SurfaceHolder surfaceHolder) {
             super.onCreate(surfaceHolder);
             mBackground = mWallpaperManager.getDrawable();
+            mBounds.left = mBounds.top = 0;
+            mBounds.right = mBackground.getIntrinsicWidth();
+            mBounds.bottom = mBackground.getIntrinsicHeight();
+            int offx = (getDesiredMinimumWidth() - mBounds.right) / 2;
+            int offy = (getDesiredMinimumHeight() - mBounds.bottom) / 2;
+            mBounds.offset(offx, offy);
+            mBackground.setBounds(mBounds);
+            surfaceHolder.setSizeFromLayout();
         }
 
         @Override
@@ -77,6 +89,14 @@
         }
         
         @Override
+        public void onOffsetsChanged(float xOffset, float yOffset,
+                int xPixels, int yPixels) {
+            mXOffset = xPixels;
+            mYOffset = yPixels;
+            drawFrame();
+        }
+
+        @Override
         public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
             super.onSurfaceChanged(holder, format, width, height);
             drawFrame();
@@ -94,19 +114,17 @@
         
         void drawFrame() {
             SurfaceHolder sh = getSurfaceHolder();
-            Canvas c = null;
-            try {
-                c = sh.lockCanvas();
-                if (c != null) {
-                    final Rect frame = sh.getSurfaceFrame();
-                    synchronized (mLock) {
-                        final Drawable background = mBackground;
-                        background.setBounds(frame);
-                        background.draw(c);
-                    }
+            Canvas c = sh.lockCanvas();
+            if (c != null) {
+                //final Rect frame = sh.getSurfaceFrame();
+                synchronized (mLock) {
+                    final Drawable background = mBackground;
+                    //background.setBounds(frame);
+                    c.translate(mXOffset, mYOffset);
+                    c.drawColor(0xff000000);
+                    background.draw(c);
                 }
-            } finally {
-                if (c != null) sh.unlockCanvasAndPost(c);
+                sh.unlockCanvasAndPost(c);
             }
         }
 
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index 7449067..a030db7 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -65,4 +65,7 @@
 
     public void executeCommand(String command, String parameters, ParcelFileDescriptor out) {
     }
+    
+    public void dispatchWallpaperOffsets(float x, float y) {
+    }
 }
diff --git a/core/java/com/android/internal/widget/ContactHeaderWidget.java b/core/java/com/android/internal/widget/ContactHeaderWidget.java
index eac5d2d..30349b3 100644
--- a/core/java/com/android/internal/widget/ContactHeaderWidget.java
+++ b/core/java/com/android/internal/widget/ContactHeaderWidget.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.widget;
 
+import android.Manifest;
 import android.content.AsyncQueryHandler;
 import android.content.ContentResolver;
 import android.content.ContentUris;
@@ -26,6 +27,7 @@
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.Message;
@@ -35,6 +37,7 @@
 import android.provider.ContactsContract.Data;
 import android.provider.ContactsContract.Intents;
 import android.provider.ContactsContract.PhoneLookup;
+import android.provider.ContactsContract.Presence;
 import android.provider.ContactsContract.RawContacts;
 import android.provider.ContactsContract.CommonDataKinds.Photo;
 import android.provider.SocialContract.Activities;
@@ -50,8 +53,14 @@
 
 import com.android.internal.R;
 
-
-/* Widget that is used across system apps for displaying a header banner with contact info */
+/**
+ * Header used across system for displaying a title bar with contact info. You
+ * can bind specific values on the header, or use helper methods like
+ * {@link #bindFromContactId(long)} to populate asynchronously.
+ * <p>
+ * The parent must request the {@link Manifest.permission#READ_CONTACTS}
+ * permission to access contact data.
+ */
 public class ContactHeaderWidget extends FrameLayout implements View.OnClickListener,
         View.OnLongClickListener {
 
@@ -61,17 +70,21 @@
     private TextView mPhoneticNameView;
     private CheckBox mStarredView;
     private ImageView mPhotoView;
+    private ImageView mPresenceView;
     private TextView mStatusView;
     private int mNoPhotoResource;
     private QueryHandler mQueryHandler;
 
     protected long mContactId;
-    protected Uri mContactDataUri;
+    protected Uri mContactSummaryUri;
     protected Uri mContactUri;
     protected Uri mStatusUri;
 
     protected ContentResolver mContentResolver;
 
+    /**
+     * Interface for callbacks invoked when the user interacts with a header.
+     */
     public interface ContactHeaderListener {
         public void onPhotoLongClick(View view);
         public void onDisplayNameLongClick(View view);
@@ -84,12 +97,14 @@
         Contacts.DISPLAY_NAME,
         Contacts.STARRED,
         Contacts.PHOTO_ID,
+        Contacts.PRESENCE_STATUS,
     };
     protected static final int HEADER_DISPLAY_NAME_COLUMN_INDEX = 0;
     //TODO: We need to figure out how we're going to get the phonetic name.
     //static final int HEADER_PHONETIC_NAME_COLUMN_INDEX
     protected static final int HEADER_STARRED_COLUMN_INDEX = 1;
     protected static final int HEADER_PHOTO_ID_COLUMN_INDEX = 2;
+    protected static final int HEADER_PRESENCE_STATUS_COLUMN_INDEX = 3;
 
     //Projection used for finding the most recent social status.
     protected static final String[] SOCIAL_PROJECTION = new String[] {
@@ -144,6 +159,8 @@
         mPhotoView.setOnClickListener(this);
         mPhotoView.setOnLongClickListener(this);
 
+        mPresenceView = (ImageView) findViewById(R.id.presence);
+
         mStatusView = (TextView)findViewById(R.id.status);
 
         // Set the photo with a random "no contact" image
@@ -163,6 +180,9 @@
         mQueryHandler = new QueryHandler(mContentResolver);
     }
 
+    /**
+     * Set the given {@link ContactHeaderListener} to handle header events.
+     */
     public void setContactHeaderListener(ContactHeaderListener listener) {
         mListener = listener;
     }
@@ -216,24 +236,6 @@
         }
     }
 
-
-    /** {@inheritDoc} */
-    public void onQueryComplete(int token, Object cookie, Cursor cursor) {
-        try{
-            if (token == TOKEN_CONTACT_INFO) {
-                bindContactInfo(cursor);
-                invalidate();
-            } else if (token == TOKEN_SOCIAL) {
-                bindSocial(cursor);
-                invalidate();
-            }
-        } finally {
-            if (cursor != null) {
-                cursor.close();
-            }
-        }
-    }
-
     /**
      * Turn on/off showing of the star element.
      */
@@ -242,6 +244,54 @@
     }
 
     /**
+     * Manually set the starred state of this header widget. This doesn't change
+     * the underlying {@link Contacts} value, only the UI state.
+     */
+    public void setStared(boolean starred) {
+        mStarredView.setChecked(starred);
+    }
+
+    /**
+     * Manually set the presence.
+     */
+    public void setPresence(int presence) {
+        mPresenceView.setImageResource(Presence.getPresenceIconResourceId(presence));
+    }
+
+    /**
+     * Manually set the contact uri
+     */
+    public void setContactUri(Uri uri) {
+        mContactUri = uri;
+    }
+
+    /**
+     * Manually set the photo to display in the header. This doesn't change the
+     * underlying {@link Contacts}, only the UI state.
+     */
+    public void setPhoto(Bitmap bitmap) {
+        mPhotoView.setImageBitmap(bitmap);
+    }
+
+    /**
+     * Manually set the display name and phonetic name to show in the header.
+     * This doesn't change the underlying {@link Contacts}, only the UI state.
+     */
+    public void setDisplayName(CharSequence displayName, CharSequence phoneticName) {
+        mDisplayNameView.setText(displayName);
+        if (mPhoneticNameView != null) {
+            mPhoneticNameView.setText(phoneticName);
+        }
+    }
+
+    /**
+     * Manually set the social snippet text to display in the header.
+     */
+    public void setSocialSnippet(CharSequence snippet) {
+        mStatusView.setText(snippet);
+    }
+
+    /**
      * Convenience method for binding all available data from an existing
      * contact.
      *
@@ -250,10 +300,29 @@
     public void bindFromContactId(long contactId) {
         mContactId = contactId;
         mContactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, mContactId);
-        mContactDataUri = Uri.withAppendedPath(mContactUri, Contacts.Data.CONTENT_DIRECTORY);
-        mStatusUri = ContentUris.withAppendedId(
-                SocialContract.Activities.CONTENT_CONTACT_STATUS_URI, mContactId);
-        redrawHeader();
+
+        bindSummaryUri(ContentUris.withAppendedId(Contacts.CONTENT_SUMMARY_URI, mContactId));
+        bindSocialUri(ContentUris.withAppendedId(Activities.CONTENT_CONTACT_STATUS_URI, mContactId));
+    }
+
+    /**
+     * Convenience method for binding {@link Contacts} header details from a
+     * {@link Contacts#CONTENT_SUMMARY_URI} reference.
+     */
+    public void bindSummaryUri(Uri contactSummary) {
+        mContactSummaryUri = contactSummary;
+        mQueryHandler.startQuery(TOKEN_CONTACT_INFO, null, mContactSummaryUri, HEADER_PROJECTION,
+                null, null, null);
+    }
+
+    /**
+     * Convenience method for binding {@link Activities} header details from a
+     * {@link Activities#CONTENT_CONTACT_STATUS_URI}.
+     */
+    public void bindSocialUri(Uri contactSocial) {
+        mStatusUri = contactSocial;
+        mQueryHandler.startQuery(TOKEN_SOCIAL, null, mStatusUri, SOCIAL_PROJECTION, null, null,
+                null);
     }
 
     /**
@@ -270,11 +339,11 @@
             c = mContentResolver.query(Uri.withAppendedPath(
                     RawContacts.CONTENT_FILTER_EMAIL_URI, Uri.encode(emailAddress)),
                     EMAIL_LOOKUP_PROJECTION, null, null, null);
-            if (c.moveToFirst()) {
+            if (c != null && c.moveToFirst()) {
                 long contactId = c.getLong(EMAIL_LOOKUP_CONTACT_ID_COLUMN_INDEX);
                 bindFromContactId(contactId);
             } else {
-                bindStatic(emailAddress, "");
+                setDisplayName(emailAddress, null);
             }
         } finally {
             if (c != null) {
@@ -296,11 +365,11 @@
         try {
             c = mContentResolver.query(Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, number),
                     PHONE_LOOKUP_PROJECTION, null, null, null);
-            if (c.moveToFirst()) {
+            if (c != null && c.moveToFirst()) {
                 long contactId = c.getLong(PHONE_LOOKUP_CONTACT_ID_COLUMN_INDEX);
                 bindFromContactId(contactId);
             } else {
-                bindStatic(number, "");
+                setDisplayName(number, null);
             }
         } finally {
             if (c != null) {
@@ -309,60 +378,39 @@
         }
     }
 
-    public void bindStatic(String main, String secondary) {
-        mDisplayNameView.setText(main);
-        mStatusView.setText(secondary);
-        mStarredView.setVisibility(View.GONE);
-        mPhotoView.setImageBitmap(loadPlaceholderPhoto(null));
-    }
-
-    protected void redrawHeader() {
-        if (mContactDataUri != null) {
-            mQueryHandler.startQuery(TOKEN_CONTACT_INFO, null, mContactDataUri, HEADER_PROJECTION,
-                    null, null, null);
-        }
-
-        if (mStatusUri != null) {
-            mQueryHandler.startQuery(TOKEN_SOCIAL, null, mStatusUri, SOCIAL_PROJECTION,
-                    null, null, null);
-        }
-    }
-
+    /**
+     * Bind the contact details provided by the given {@link Cursor}.
+     */
     protected void bindContactInfo(Cursor c) {
-        if (c == null) {
-            return;
-        }
-        if (c.moveToFirst()) {
-            //Set name
-            String displayName = c.getString(HEADER_DISPLAY_NAME_COLUMN_INDEX);
-            Log.i(TAG, displayName);
-            mDisplayNameView.setText(displayName);
-            //TODO: Bring back phonetic name
-            /*if (mPhoneticNameView != null) {
-                String phoneticName = c.getString(CONTACT_PHONETIC_NAME_COLUMN);
-                mPhoneticNameView.setText(phoneticName);
-            }*/
+        if (c == null || !c.moveToFirst()) return;
 
-            //Set starred
-            mStarredView.setChecked(c.getInt(HEADER_STARRED_COLUMN_INDEX) == 1);
+        // TODO: Bring back phonetic name
+        final String displayName = c.getString(HEADER_DISPLAY_NAME_COLUMN_INDEX);
+        final String phoneticName = null;
+        this.setDisplayName(displayName, null);
 
-            //Set the photo
-            Bitmap photoBitmap = loadContactPhoto(c.getLong(HEADER_PHOTO_ID_COLUMN_INDEX), null);
-            if (photoBitmap == null) {
-                photoBitmap = loadPlaceholderPhoto(null);
-            }
-            mPhotoView.setImageBitmap(photoBitmap);
+        final boolean starred = c.getInt(HEADER_STARRED_COLUMN_INDEX) != 0;
+        mStarredView.setChecked(starred);
+
+        //Set the photo
+        Bitmap photoBitmap = loadContactPhoto(c.getLong(HEADER_PHOTO_ID_COLUMN_INDEX), null);
+        if (photoBitmap == null) {
+            photoBitmap = loadPlaceholderPhoto(null);
         }
+        mPhotoView.setImageBitmap(photoBitmap);
+
+        //Set the presence status
+        int presence = c.getInt(HEADER_PRESENCE_STATUS_COLUMN_INDEX);
+        mPresenceView.setImageResource(Presence.getPresenceIconResourceId(presence));
     }
 
+    /**
+     * Bind the social data provided by the given {@link Cursor}.
+     */
     protected void bindSocial(Cursor c) {
-        if (c == null) {
-            return;
-        }
-        if (c.moveToFirst()) {
-            String status = c.getString(SOCIAL_TITLE_COLUMN_INDEX);
-            mStatusView.setText(status);
-        }
+        if (c == null || !c.moveToFirst()) return;
+        final String status = c.getString(SOCIAL_TITLE_COLUMN_INDEX);
+        this.setSocialSnippet(status);
     }
 
     public void onClick(View view) {
@@ -408,7 +456,7 @@
                     new String[] { Photo.PHOTO },
                     null, null, null);
 
-            if (photoCursor.moveToFirst() && !photoCursor.isNull(0)) {
+            if (photoCursor != null && photoCursor.moveToFirst() && !photoCursor.isNull(0)) {
                 byte[] photoData = photoCursor.getBlob(0);
                 photoBm = BitmapFactory.decodeByteArray(photoData, 0,
                         photoData.length, options);
diff --git a/core/jni/android_os_SystemProperties.cpp b/core/jni/android_os_SystemProperties.cpp
index ca4fa11..406884b 100644
--- a/core/jni/android_os_SystemProperties.cpp
+++ b/core/jni/android_os_SystemProperties.cpp
@@ -36,9 +36,9 @@
                                 "key must not be null.");
         goto error;
     }
-    
+
     key = env->GetStringUTFChars(keyJ, NULL);
-    
+
     len = property_get(key, buf, "");
     if ((len <= 0) && (defJ != NULL)) {
         rvJ = defJ;
@@ -47,9 +47,9 @@
     } else {
         rvJ = env->NewStringUTF("");
     }
-    
+
     env->ReleaseStringUTFChars(keyJ, key);
-    
+
 error:
     return rvJ;
 }
@@ -60,6 +60,101 @@
     return SystemProperties_getSS(env, clazz, keyJ, NULL);
 }
 
+static jint SystemProperties_get_int(JNIEnv *env, jobject clazz,
+                                      jstring keyJ, jint defJ)
+{
+    int len;
+    const char* key;
+    char buf[PROPERTY_VALUE_MAX];
+    jint result = defJ;
+
+    if (keyJ == NULL) {
+        jniThrowException(env, "java/lang/NullPointerException",
+                                "key must not be null.");
+        goto error;
+    }
+
+    key = env->GetStringUTFChars(keyJ, NULL);
+
+    len = property_get(key, buf, "");
+    if (len > 0) {
+        jint temp;
+        if (sscanf(buf, "%d", &temp) == 1)
+            result = temp;
+    }
+
+    env->ReleaseStringUTFChars(keyJ, key);
+
+error:
+    return result;
+}
+
+static jlong SystemProperties_get_long(JNIEnv *env, jobject clazz,
+                                      jstring keyJ, jlong defJ)
+{
+    int len;
+    const char* key;
+    char buf[PROPERTY_VALUE_MAX];
+    jlong result = defJ;
+
+    if (keyJ == NULL) {
+        jniThrowException(env, "java/lang/NullPointerException",
+                                "key must not be null.");
+        goto error;
+    }
+
+    key = env->GetStringUTFChars(keyJ, NULL);
+
+    len = property_get(key, buf, "");
+    if (len > 0) {
+        jlong temp;
+        if (sscanf(buf, "%lld", &temp) == 1)
+            result = temp;
+    }
+
+    env->ReleaseStringUTFChars(keyJ, key);
+
+error:
+    return result;
+}
+
+static jboolean SystemProperties_get_boolean(JNIEnv *env, jobject clazz,
+                                      jstring keyJ, jboolean defJ)
+{
+    int len;
+    const char* key;
+    char buf[PROPERTY_VALUE_MAX];
+    jboolean result = defJ;
+
+    if (keyJ == NULL) {
+        jniThrowException(env, "java/lang/NullPointerException",
+                                "key must not be null.");
+        goto error;
+    }
+
+    key = env->GetStringUTFChars(keyJ, NULL);
+
+    len = property_get(key, buf, "");
+    if (len == 1) {
+        char ch = buf[0];
+        if (ch == '0' || ch == 'n')
+            result = false;
+        else if (ch == '1' || ch == 'y')
+            result = true;
+    } else if (len > 1) {
+         if (!strcmp(buf, "no") || !strcmp(buf, "false") || !strcmp(buf, "off")) {
+            result = false;
+        } else if (!strcmp(buf, "yes") || !strcmp(buf, "true") || !strcmp(buf, "on")) {
+            result = true;
+        }
+    }
+
+    env->ReleaseStringUTFChars(keyJ, key);
+
+error:
+    return result;
+}
+
 static void SystemProperties_set(JNIEnv *env, jobject clazz,
                                       jstring keyJ, jstring valJ)
 {
@@ -94,6 +189,12 @@
       (void*) SystemProperties_getS },
     { "native_get", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
       (void*) SystemProperties_getSS },
+    { "native_get_int", "(Ljava/lang/String;I)I",
+      (void*) SystemProperties_get_int },
+    { "native_get_long", "(Ljava/lang/String;J)J",
+      (void*) SystemProperties_get_long },
+    { "native_get_boolean", "(Ljava/lang/String;Z)Z",
+      (void*) SystemProperties_get_boolean },
     { "native_set", "(Ljava/lang/String;Ljava/lang/String;)V",
       (void*) SystemProperties_set },
 };
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 66b2506..562cc8f 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -1536,6 +1536,22 @@
     return Asset::getGlobalCount();
 }
 
+static jobject android_content_AssetManager_getAssetAllocations(JNIEnv* env, jobject clazz)
+{
+    String8 alloc = Asset::getAssetAllocations();
+    if (alloc.length() <= 0) {
+        return NULL;
+    }
+    
+    jstring str = env->NewStringUTF(alloc.string());
+    if (str == NULL) {
+        doThrow(env, "java/lang/OutOfMemoryError");
+        return NULL;
+    }
+    
+    return str;
+}
+
 static jint android_content_AssetManager_getGlobalAssetManagerCount(JNIEnv* env, jobject clazz)
 {
     return AssetManager::getGlobalCount();
@@ -1646,6 +1662,8 @@
         (void*) android_content_AssetManager_destroy },
     { "getGlobalAssetCount", "()I",
         (void*) android_content_AssetManager_getGlobalAssetCount },
+    { "getAssetAllocations", "()Ljava/lang/String;",
+        (void*) android_content_AssetManager_getAssetAllocations },
     { "getGlobalAssetManagerCount", "()I",
         (void*) android_content_AssetManager_getGlobalAssetCount },
 };
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index cf85af5..608c1ff 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1046,6 +1046,13 @@
         android:description="@string/permdesc_backup"
         android:protectionLevel="signatureOrSystem" />
 
+    <!-- Allows an application to participate in the backup and restore process
+         @hide -->
+    <permission android:name="android.permission.BACKUP_DATA"
+        android:label="@string/permlab_backup_data"
+        android:description="@string/permdesc_backup_data"
+        android:protectionLevel="signatureOrSystem" />
+
     <!-- Allows an application to tell the AppWidget service which application
          can access AppWidget's data.  The normal user flow is that a user
          picks an AppWidget to go into a particular host, thereby giving that
@@ -1157,9 +1164,6 @@
 
         <service android:name="com.android.internal.service.wallpaper.ImageWallpaper"
                 android:permission="android.permission.BIND_WALLPAPER">
-            <intent-filter>
-                <action android:name="android.service.wallpaper.WallpaperService" />
-            </intent-filter>
         </service>
 
         <receiver android:name="com.android.server.BootReceiver" >
diff --git a/core/res/res/drawable/sym_def_app_icon.png b/core/res/res/drawable/sym_def_app_icon.png
index 7502484..8be3b54 100644
--- a/core/res/res/drawable/sym_def_app_icon.png
+++ b/core/res/res/drawable/sym_def_app_icon.png
Binary files differ
diff --git a/core/res/res/layout-ja/contact_header_name.xml b/core/res/res/layout-ja/contact_header_name.xml
index 03332b1..20df5c6 100644
--- a/core/res/res/layout-ja/contact_header_name.xml
+++ b/core/res/res/layout-ja/contact_header_name.xml
@@ -25,6 +25,8 @@
     <TextView android:id="@+id/name"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:singleLine="true"
+        android:ellipsize="end"
     	android:textAppearance="?android:attr/textAppearanceLargeInverse"
     	android:textColor="@android:color/secondary_text_light"
         />
@@ -32,6 +34,8 @@
     <TextView android:id="@+id/phonetic_name"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
+        android:singleLine="true"
+        android:ellipsize="end"
     	android:textAppearance="?android:attr/textAppearanceSmallInverse"
     	android:textColor="@android:color/secondary_text_light"
         />
diff --git a/core/res/res/layout/contact_header.xml b/core/res/res/layout/contact_header.xml
index 06cd38c..73e379b 100644
--- a/core/res/res/layout/contact_header.xml
+++ b/core/res/res/layout/contact_header.xml
@@ -48,6 +48,13 @@
                 
     </LinearLayout>
 
+    <ImageView
+        android:id="@+id/presence"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:paddingLeft="3dip"
+        android:paddingRight="6dip"/>
+        
     <CheckBox
         android:id="@+id/star"
         android:layout_width="wrap_content"
diff --git a/core/res/res/layout/contact_header_name.xml b/core/res/res/layout/contact_header_name.xml
index aec943e..9039702 100644
--- a/core/res/res/layout/contact_header_name.xml
+++ b/core/res/res/layout/contact_header_name.xml
@@ -19,8 +19,8 @@
     android:id="@+id/name"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
-    android:textAppearance="?android:attr/textAppearanceLargeInverse"
+    android:textAppearance="?android:attr/textAppearanceMediumInverse"
     android:textColor="@android:color/secondary_text_light"
-    android:maxLines="2"
+    android:singleLine="true"
     android:ellipsize="end"
     />
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 48b565f..442357e 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -577,9 +577,7 @@
          backup and restore of the application's settings to external storage. -->
     <attr name="backupAgent" format="string" />
 
-    <!-- Whether the application allows its data to be backed up at all.  This
-         attribute defaults to 'true':  unless the application opts out, the
-         user will be able to back up its data to desktop storage. -->
+    <!-- This is not the attribute you are looking for. -->
     <attr name="allowBackup" format="boolean" />
 
     <!-- The <code>manifest</code> tag is the root of an
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index f655b27..92c776c 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -38,4 +38,23 @@
     <!-- Flag indicating whether Last Name comes before First Name.
         This becomes true in Japan, for example.-->
     <bool name="config_lastname_comes_before_firstname">false</bool>
+
+    <!-- This string array should be overridden by the device to present a list of network attributes.  This is used by the connectivity manager to decide which networks can coexist based on the hardward -->
+    <!-- An Array of "[type-name],[associated radio-name],[priority]  -->
+    <string-array translatable="false" name="networkAttributes">
+        <item>"default,wifi,0"</item>
+        <item>"default,mobile,0"</item>
+        <item>"mms,mobile,1"</item>
+        <item>"supl,mobile,1"</item>
+        <item>"dun,mobile,1"</item>
+        <item>"hipri,mobile,2"</item>
+    </string-array>
+
+    <!-- This string array should be overridden by the device to present a list of radio attributes.  This is used by the connectivity manager to decide which networks can coexist based on the hardware -->
+    <!-- An Array of "[radio-name],[priority]                        -->
+    <!--              [# simultaneous connection types]"             -->
+    <string-array translatable="false" name="radioAttributes">
+        <item>"wifi,1,1"</item>
+        <item>"mobile,0,1"</item>
+    </string-array>
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index ef87b17..d51b439 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1092,73 +1092,54 @@
   <eat-comment />
 
   <public type="attr" name="tension" id="0x0101026a" />
-  <public type="attr" name="extraTension" />
-  <public type="attr" name="anyDensity" />
-  <public type="attr" name="searchSuggestThreshold" />
-  <public type="attr" name="includeInGlobalSearch" />
-  <public type="attr" name="onClick" />
-  <public type="attr" name="targetSdkVersion" />
-  <public type="attr" name="maxSdkVersion" />
-  <public type="attr" name="testOnly" />
-  <public type="attr" name="contentDescription" />
-  <public type="attr" name="gestureStrokeWidth" />
-  <public type="attr" name="gestureColor" />
-  <public type="attr" name="uncertainGestureColor" />
-  <public type="attr" name="fadeOffset" />
-  <public type="attr" name="fadeDuration" />
-  <public type="attr" name="gestureStrokeType" />
-  <public type="attr" name="gestureStrokeLengthThreshold" />
-  <public type="attr" name="gestureStrokeSquarenessThreshold" />
-  <public type="attr" name="gestureStrokeAngleThreshold" />
-  <public type="attr" name="eventsInterceptionEnabled" />
-  <public type="attr" name="fadeEnabled" />
-  <public type="attr" name="backupAgent" />
-  <public type="attr" name="allowBackup" />
-  <public type="attr" name="glEsVersion" />
-  <public type="attr" name="queryAfterZeroResults" />
-  <public type="attr" name="dropDownHeight" />
-  <public type="attr" name="smallScreens" />
-  <public type="attr" name="normalScreens" />
-  <public type="attr" name="largeScreens" />
-  <public type="attr" name="progressBarStyleInverse" />
-  <public type="attr" name="progressBarStyleSmallInverse" />
-  <public type="attr" name="progressBarStyleLargeInverse" /> 
-  <public type="attr" name="searchSettingsDescription" />
-  <public type="attr" name="textColorPrimaryInverseDisableOnly" />
-  <public type="attr" name="autoUrlDetect" />
-  <public type="attr" name="resizeable" />
+  <public type="attr" name="extraTension" id="0x0101026b" />
+  <public type="attr" name="anyDensity" id="0x0101026c" />
+  <public type="attr" name="searchSuggestThreshold" id="0x0101026d" />
+  <public type="attr" name="includeInGlobalSearch" id="0x0101026e" />
+  <public type="attr" name="onClick" id="0x0101026f" />
+  <public type="attr" name="targetSdkVersion" id="0x01010270" />
+  <public type="attr" name="maxSdkVersion" id="0x01010271" />
+  <public type="attr" name="testOnly" id="0x01010272" />
+  <public type="attr" name="contentDescription" id="0x01010273" />
+  <public type="attr" name="gestureStrokeWidth" id="0x01010274" />
+  <public type="attr" name="gestureColor" id="0x01010275" />
+  <public type="attr" name="uncertainGestureColor" id="0x01010276" />
+  <public type="attr" name="fadeOffset" id="0x01010277" />
+  <public type="attr" name="fadeDuration" id="0x01010278" />
+  <public type="attr" name="gestureStrokeType" id="0x01010279" />
+  <public type="attr" name="gestureStrokeLengthThreshold" id="0x0101027a" />
+  <public type="attr" name="gestureStrokeSquarenessThreshold" id="0x0101027b" />
+  <public type="attr" name="gestureStrokeAngleThreshold" id="0x0101027c" />
+  <public type="attr" name="eventsInterceptionEnabled" id="0x0101027d" />
+  <public type="attr" name="fadeEnabled" id="0x0101027e" />
+  <public type="attr" name="backupAgent" id="0x0101027f" />
+  <public type="attr" name="allowBackup" id="0x01010280" />
+  <public type="attr" name="glEsVersion" id="0x01010281" />
+  <public type="attr" name="queryAfterZeroResults" id="0x01010282" />
+  <public type="attr" name="dropDownHeight" id="0x01010283" />
+  <public type="attr" name="smallScreens" id="0x01010284" />
+  <public type="attr" name="normalScreens" id="0x01010285" />
+  <public type="attr" name="largeScreens" id="0x01010286" />
+  <public type="attr" name="progressBarStyleInverse" id="0x01010287" />
+  <public type="attr" name="progressBarStyleSmallInverse" id="0x01010288" />
+  <public type="attr" name="progressBarStyleLargeInverse" id="0x01010289" />
+  <public type="attr" name="searchSettingsDescription" id="0x0101028a" />
+  <public type="attr" name="textColorPrimaryInverseDisableOnly" id="0x0101028b" />
+  <public type="attr" name="autoUrlDetect" id="0x0101028c" />
+  <public type="attr" name="resizeable" id="0x0101028d" />
 
-  <public-padding type="attr" name="donut_resource_pad" end="0x0101029f" />
-
-  <public-padding type="id" name="donut_resource_pad" end="0x01020040" />
-  
   <public type="style" name="Widget.ProgressBar.Inverse" id="0x0103005b" />
   <public type="style" name="Widget.ProgressBar.Large.Inverse" id="0x0103005c" />
   <public type="style" name="Widget.ProgressBar.Small.Inverse" id="0x0103005d" /> 
-  <public-padding type="style" name="donut_resource_pad" end="0x01030070" />
-  
-  <public-padding type="string" name="donut_resource_pad" end="0x01040030" />
 
-  <public-padding type="dimen" name="donut_resource_pad" end="0x01050010" />
-
-  <public-padding type="color" name="donut_resource_pad" end="0x01060030" />
-
-  <public-padding type="array" name="donut_resource_pad" end="0x01070010" />
-
-  <public-padding type="anim" name="donut_resource_pad" end="0x010a0020" />
+  <public type="drawable" name="stat_sys_vp_phone_call" id="0x010800a7" />
+  <public type="drawable" name="stat_sys_vp_phone_call_on_hold" id="0x010800a8" />
   
-  <public-padding type="integer" name="donut_resource_pad" end="0x010e0010" />
-  
-  <public type="anim" name="anticipate_interpolator" />
-  <public type="anim" name="overshoot_interpolator" />
-  <public type="anim" name="anticipate_overshoot_interpolator" />
-  <public type="anim" name="bounce_interpolator" />
-  <public type="anim" name="linear_interpolator" />
-  
-  <public-padding type="drawable" name="donut_resource_pad" end="0x010800d0" />
-  
-  <public-padding type="layout" name="donut_resource_pad" end="0x01090020" />
-  
+  <public type="anim" name="anticipate_interpolator" id="0x010a0007" />
+  <public type="anim" name="overshoot_interpolator" id="0x010a0008" />
+  <public type="anim" name="anticipate_overshoot_interpolator" id="0x010a0009" />
+  <public type="anim" name="bounce_interpolator" id="0x010a000a" />
+  <public type="anim" name="linear_interpolator" id="0x010a000b" />
   
 <!-- ===============================================================
      Resources added in Eclair.
@@ -1169,9 +1150,6 @@
   <public type="attr" name="contentAuthority" />
   <public type="attr" name="windowShowWallpaper" />
 
-  <public type="drawable" name="stat_sys_vp_phone_call" />
-  <public type="drawable" name="stat_sys_vp_phone_call_on_hold" />
-  
   <public type="style" name="Theme.Wallpaper" />
   <public type="style" name="Theme.Wallpaper.NoTitleBar" />
   <public type="style" name="Theme.Wallpaper.NoTitleBar.Fullscreen" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 68f2070..815b767 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -552,6 +552,11 @@
     <string name="permdesc_backup">Allows the application to control the system's backup and restore mechanism.  Not for use by normal applications.</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_backup_data">back up and restore the application's data</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_backup_data">Allows the application to participate in the system's backup and restore mechanism.</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_internalSystemWindow">display unauthorized windows</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_internalSystemWindow">Allows the creation of
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 1e3a4a8..bfdce1e 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -112,6 +112,7 @@
         <item name="windowFullscreen">false</item>
         <item name="windowIsFloating">false</item>
         <item name="windowContentOverlay">@android:drawable/title_bar_shadow</item>
+        <item name="windowShowWallpaper">false</item>
         <item name="windowTitleStyle">@android:style/WindowTitle</item>
         <item name="windowTitleSize">25dip</item>
         <item name="windowTitleBackgroundStyle">@android:style/WindowTitleBackground</item>
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index ca35a40..50d39b7 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -16,6 +16,8 @@
 
 package android.renderscript;
 
+import java.lang.reflect.Field;
+import java.lang.reflect.Array;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -33,9 +35,12 @@
  *
  **/
 public class Allocation extends BaseObj {
-    Allocation(int id, RenderScript rs) {
+    Type mType;
+
+    Allocation(int id, RenderScript rs, Type t) {
         super(rs);
         mID = id;
+        mType = t;
     }
 
     public void uploadToTexture(int baseMipLevel) {
@@ -82,6 +87,10 @@
         mRS.nAllocationRead(mID, d);
     }
 
+    public void data(Object o) {
+        mRS.nAllocationDataFromObject(mID, mType, o);
+    }
+
 
     public class Adapter1D extends BaseObj {
         Adapter1D(int id, RenderScript rs) {
@@ -179,7 +188,7 @@
             throw new IllegalStateException("Bad Type");
         }
         int id = rs.nAllocationCreateTyped(type.mID);
-        return new Allocation(id, rs);
+        return new Allocation(id, rs, type);
     }
 
     static public Allocation createSized(RenderScript rs, Element e, int count)
@@ -194,7 +203,7 @@
                 throw new IllegalStateException("Bad element.");
             }
         }
-        return new Allocation(id, rs);
+        return new Allocation(id, rs, null);
     }
 
     static public Allocation createFromBitmap(RenderScript rs, Bitmap b, Element dstFmt, boolean genMips)
@@ -204,7 +213,7 @@
         }
 
         int id = rs.nAllocationCreateFromBitmap(dstFmt.mPredefinedID, genMips, b);
-        return new Allocation(id, rs);
+        return new Allocation(id, rs, null);
     }
 
     static public Allocation createFromBitmapBoxed(RenderScript rs, Bitmap b, Element dstFmt, boolean genMips)
@@ -214,7 +223,7 @@
         }
 
         int id = rs.nAllocationCreateFromBitmapBoxed(dstFmt.mPredefinedID, genMips, b);
-        return new Allocation(id, rs);
+        return new Allocation(id, rs, null);
     }
 
     static public Allocation createFromBitmapResource(RenderScript rs, Resources res, int id, Element dstFmt, boolean genMips)
@@ -230,8 +239,20 @@
         Bitmap b = BitmapFactory.decodeResource(res, id, mBitmapOptions);
         return createFromBitmapBoxed(rs, b, dstFmt, genMips);
     }
-
-
+/*
+    public static Allocation createFromObject(RenderScript rs, Object o) {
+        Class c = o.getClass();
+        Type t;
+        if(c.isArray()) {
+            t = Type.createFromClass(rs, c, Array.getLength(o));
+        } else {
+            t = Type.createFromClass(rs, c, 1);
+        }
+        Allocation alloc = createTyped(rs, t);
+        t.destroy();
+        return alloc;
+    } 
+*/
 }
 
 
diff --git a/graphics/java/android/renderscript/Element.java b/graphics/java/android/renderscript/Element.java
index 14d9115..9155da8 100644
--- a/graphics/java/android/renderscript/Element.java
+++ b/graphics/java/android/renderscript/Element.java
@@ -16,6 +16,10 @@
 
 package android.renderscript;
 
+import android.util.Config;
+import android.util.Log;
+
+import java.lang.reflect.Field;
 
 /**
  * @hide
@@ -144,7 +148,26 @@
         mRS.nElementDestroy(mID);
     }
 
+    public static Element createFromClass(RenderScript rs, Class c) {
+        Field[] fields = c.getFields();
+        Builder b = new Builder(rs);
 
+        for(Field f: fields) {
+            Class fc = f.getType();
+            if(fc == int.class) {
+                b.add(Element.DataType.SIGNED, Element.DataKind.USER, false, 32, f.getName());
+            } else if(fc == short.class) {
+                b.add(Element.DataType.SIGNED, Element.DataKind.USER, false, 16, f.getName());
+            } else if(fc == byte.class) {
+                b.add(Element.DataType.SIGNED, Element.DataKind.USER, false, 8, f.getName());
+            } else if(fc == float.class) {
+                b.add(Element.DataType.FLOAT, Element.DataKind.USER, false, 32, f.getName());
+            } else {
+                throw new IllegalArgumentException("Unkown field type");
+            }
+        }
+        return b.create();
+    }
 
 
     public static class Builder {
@@ -158,6 +181,7 @@
             Element.DataKind mKind;
             boolean mIsNormalized;
             int mBits;
+            String mName;
         }
 
         public Builder(RenderScript rs) {
@@ -188,16 +212,22 @@
             return this;
         }
 
-        public Builder add(Element.DataType dt, Element.DataKind dk, boolean isNormalized, int bits) {
+        public Builder add(Element.DataType dt, Element.DataKind dk, boolean isNormalized, int bits, String name) {
             Entry en = new Entry();
             en.mType = dt;
             en.mKind = dk;
             en.mIsNormalized = isNormalized;
             en.mBits = bits;
+            en.mName = name;
             addEntry(en);
             return this;
         }
 
+        public Builder add(Element.DataType dt, Element.DataKind dk, boolean isNormalized, int bits) {
+            add(dt, dk, isNormalized, bits, null);
+            return this;
+        }
+
         static synchronized Element internalCreate(RenderScript rs, Builder b) {
             rs.nElementBegin();
             for (int ct=0; ct < b.mEntryCount; ct++) {
@@ -209,7 +239,7 @@
                     if (en.mIsNormalized) {
                         norm = 1;
                     }
-                    rs.nElementAdd(en.mKind.mID, en.mType.mID, norm, en.mBits);
+                    rs.nElementAdd(en.mKind.mID, en.mType.mID, norm, en.mBits, en.mName);
                 }
             }
             int id = rs.nElementCreate();
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 77486b1..b98a48ab 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -18,9 +18,11 @@
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.lang.reflect.Field;
 
 import android.content.res.Resources;
 import android.graphics.Bitmap;
+import android.renderscript.Type;
 import android.util.Config;
 import android.util.Log;
 import android.view.Surface;
@@ -76,7 +78,7 @@
 
     native void nElementBegin();
     native void nElementAddPredefined(int predef);
-    native void nElementAdd(int kind, int type, int norm, int bits);
+    native void nElementAdd(int kind, int type, int norm, int bits, String s);
     native int  nElementCreate();
     native int  nElementGetPredefined(int predef);
     native void nElementDestroy(int obj);
@@ -85,6 +87,8 @@
     native void nTypeAdd(int dim, int val);
     native int  nTypeCreate();
     native void nTypeDestroy(int id);
+    native void nTypeFinalDestroy(Type t);
+    native void nTypeSetupFields(Type t, int[] types, int[] bits, Field[] IDs);
 
     native int  nAllocationCreateTyped(int type);
     native int  nAllocationCreatePredefSized(int predef, int count);
@@ -102,6 +106,7 @@
     native void nAllocationSubData2D(int id, int xoff, int yoff, int w, int h, float[] d);
     native void nAllocationRead(int id, int[] d);
     native void nAllocationRead(int id, float[] d);
+    native void nAllocationDataFromObject(int id, Type t, Object o);
 
     native void nTriangleMeshDestroy(int id);
     native void nTriangleMeshBegin(int vertex, int index);
@@ -137,10 +142,10 @@
     native void nScriptSetClearDepth(int script, float depth);
     native void nScriptSetClearStencil(int script, int stencil);
     native void nScriptSetTimeZone(int script, byte[] timeZone);
+    native void nScriptSetType(int type, String name, int slot);
+    native void nScriptSetRoot(boolean isRoot);
 
     native void nScriptCBegin();
-    native void nScriptCAddType(int type);
-    native void nScriptCSetRoot(boolean isRoot);
     native void nScriptCSetScript(byte[] script, int offset, int length);
     native int  nScriptCCreate();
     native void nScriptCAddDefineI32(String name, int value);
diff --git a/graphics/java/android/renderscript/Script.java b/graphics/java/android/renderscript/Script.java
index 1c7b32b..47479d8 100644
--- a/graphics/java/android/renderscript/Script.java
+++ b/graphics/java/android/renderscript/Script.java
@@ -20,7 +20,10 @@
  * @hide
  **/
 public class Script extends BaseObj {
+    public static final int MAX_SLOT = 16;
+
     boolean mIsRoot;
+    Type[] mTypes;
 
     Script(int id, RenderScript rs) {
         super(rs);
@@ -62,21 +65,37 @@
     public static class Builder {
         RenderScript mRS;
         boolean mIsRoot = false;
+        Type[] mTypes;
+        String[] mNames;
 
         Builder(RenderScript rs) {
             mRS = rs;
+            mTypes = new Type[MAX_SLOT];
+            mNames = new String[MAX_SLOT];
         }
 
-        public void addType(Type t) {
-            mRS.nScriptCAddType(t.mID);
+        public void setType(Type t, int slot) {
+            mTypes[slot] = t;
+            mNames[slot] = null;
+        }
+
+        public void setType(Type t, String name, int slot) {
+            mTypes[slot] = t;
+            mNames[slot] = name;
         }
 
         void transferCreate() {
-            mRS.nScriptCSetRoot(mIsRoot);
+            mRS.nScriptSetRoot(mIsRoot);
+            for(int ct=0; ct < mTypes.length; ct++) {
+                if(mTypes[ct] != null) {
+                    mRS.nScriptSetType(mTypes[ct].mID, mNames[ct], ct);
+                }
+            }
         }
 
         void transferObject(Script s) {
             s.mIsRoot = mIsRoot;
+            s.mTypes = mTypes;
         }
 
         public void setRoot(boolean r) {
diff --git a/graphics/java/android/renderscript/Type.java b/graphics/java/android/renderscript/Type.java
index a5fc603..afb0e60 100644
--- a/graphics/java/android/renderscript/Type.java
+++ b/graphics/java/android/renderscript/Type.java
@@ -16,10 +16,12 @@
 
 package android.renderscript;
 
+import java.lang.reflect.Field;
+
+import android.renderscript.Element;
 import android.util.Config;
 import android.util.Log;
 
-
 /**
  * @hide
  *
@@ -28,11 +30,22 @@
     Dimension[] mDimensions;
     int[] mValues;
     Element mElement;
+    private int mNativeCache;
+    Class mJavaClass;
 
 
     Type(int id, RenderScript rs) {
         super(rs);
         mID = id;
+        mNativeCache = 0;
+    }
+
+    protected void finalize() throws Throwable {
+        if(mNativeCache != 0) {
+            mRS.nTypeFinalDestroy(this);
+            mNativeCache = 0;
+        }
+        super.finalize();
     }
 
     public void destroy() {
@@ -43,6 +56,51 @@
         mRS.nTypeDestroy(mID);
     }
 
+    public static Type createFromClass(RenderScript rs, Class c, int size) {
+        Element e = Element.createFromClass(rs, c);
+        Builder b = new Builder(rs, e);
+        b.add(Dimension.X, size);
+        Type t = b.create();
+        e.destroy();
+
+        // native fields
+        {
+            Field[] fields = c.getFields();
+            int[] arTypes = new int[fields.length];
+            int[] arBits = new int[fields.length];
+
+            for(int ct=0; ct < fields.length; ct++) {
+                Field f = fields[ct];
+                Class fc = f.getType();
+                if(fc == int.class) {
+                    arTypes[ct] = Element.DataType.SIGNED.mID;
+                    arBits[ct] = 32;
+                } else if(fc == short.class) {
+                    arTypes[ct] = Element.DataType.SIGNED.mID;
+                    arBits[ct] = 16;
+                } else if(fc == byte.class) {
+                    arTypes[ct] = Element.DataType.SIGNED.mID;
+                    arBits[ct] = 8;
+                } else if(fc == float.class) {
+                    arTypes[ct] = Element.DataType.FLOAT.mID;
+                    arBits[ct] = 32;
+                } else {
+                    throw new IllegalArgumentException("Unkown field type");
+                }
+            }
+            rs.nTypeSetupFields(t, arTypes, arBits, fields);
+        }
+        t.mJavaClass = c;
+        return t;
+    }
+
+    public static Type createFromClass(RenderScript rs, Class c, int size, String scriptName) {
+        Type t = createFromClass(rs, c, size);
+        t.setName(scriptName);
+        return t;
+    }
+
+
     public static class Builder {
         RenderScript mRS;
         Entry[] mEntries;
diff --git a/graphics/jni/Android.mk b/graphics/jni/Android.mk
index a6abd8c..799fcbb 100644
--- a/graphics/jni/Android.mk
+++ b/graphics/jni/Android.mk
@@ -1,4 +1,10 @@
 
+# libRS needs libacc, which isn't 64-bit clean, and so can't be built
+# for the simulator on gHardy, and therefore libRS needs to be excluded
+# from the simulator as well, and so in turn librs_jni needs to be
+# excluded.
+ifneq ($(TARGET_SIMULATOR),true)
+
 LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
@@ -36,3 +42,4 @@
 
 include $(BUILD_SHARED_LIBRARY)
 
+endif #simulator
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 285fdc0..5780e02 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -50,6 +50,7 @@
 
 static jfieldID gContextId = 0;
 static jfieldID gNativeBitmapID = 0;
+static jfieldID gTypeNativeCache = 0;
 
 static void _nInit(JNIEnv *_env, jclass _this)
 {
@@ -57,6 +58,9 @@
 
     jclass bitmapClass = _env->FindClass("android/graphics/Bitmap");
     gNativeBitmapID = _env->GetFieldID(bitmapClass, "mNativeBitmap", "I");
+
+    jclass typeClass = _env->FindClass("android/renderscript/Type");
+    gTypeNativeCache = _env->GetFieldID(typeClass, "mNativeCache", "I");
 }
 
 
@@ -149,11 +153,18 @@
 }
 
 static void
-nElementAdd(JNIEnv *_env, jobject _this, jint kind, jint type, jint norm, jint bits)
+nElementAdd(JNIEnv *_env, jobject _this, jint kind, jint type, jint norm, jint bits, jstring name)
 {
     RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    const char* n = NULL;
+    if (name) {
+        n = _env->GetStringUTFChars(name, NULL);
+    }
     LOG_API("nElementAdd, con(%p), kind(%i), type(%i), norm(%i), bits(%i)", con, kind, type, norm, bits);
-    rsElementAdd((RsDataKind)kind, (RsDataType)type, norm != 0, (size_t)bits);
+    rsElementAdd((RsDataKind)kind, (RsDataType)type, norm != 0, (size_t)bits, n);
+    if (n) {
+        _env->ReleaseStringUTFChars(name, n);
+    }
 }
 
 static jint
@@ -214,6 +225,91 @@
     rsTypeDestroy((RsType)eID);
 }
 
+static void * SF_LoadInt(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
+{
+    ((int32_t *)buffer)[0] = _env->GetIntField(_obj, _field);
+    return ((uint8_t *)buffer) + 4;
+}
+
+static void * SF_LoadShort(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
+{
+    ((int16_t *)buffer)[0] = _env->GetShortField(_obj, _field);
+    return ((uint8_t *)buffer) + 2;
+}
+
+static void * SF_LoadByte(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
+{
+    ((int8_t *)buffer)[0] = _env->GetByteField(_obj, _field);
+    return ((uint8_t *)buffer) + 1;
+}
+
+static void * SF_LoadFloat(JNIEnv *_env, jobject _obj, jfieldID _field, void *buffer)
+{
+    ((float *)buffer)[0] = _env->GetFloatField(_obj, _field);
+    return ((uint8_t *)buffer) + 4;
+}
+
+struct TypeFieldCache {
+    jfieldID field;
+    int bits;
+    void * (*ptr)(JNIEnv *, jobject, jfieldID, void *buffer);
+};
+
+struct TypeCache {
+    int fieldCount;
+    int size;
+    TypeFieldCache fields[1];
+};
+
+//{"nTypeFinalDestroy",              "(Landroid/renderscript/Type;)V",       (void*)nTypeFinalDestroy },
+static void
+nTypeFinalDestroy(JNIEnv *_env, jobject _this, jobject _type)
+{
+    TypeCache *tc = (TypeCache *)_env->GetIntField(_type, gTypeNativeCache);
+    free(tc);
+}
+
+// native void nTypeSetupFields(Type t, int[] types, int[] bits, Field[] IDs);
+static void
+nTypeSetupFields(JNIEnv *_env, jobject _this, jobject _type, jintArray _types, jintArray _bits, jobjectArray _IDs)
+{
+    int fieldCount = _env->GetArrayLength(_types);
+    size_t structSize = sizeof(TypeCache) + (sizeof(TypeFieldCache) * (fieldCount-1));
+    TypeCache *tc = (TypeCache *)malloc(structSize);
+    memset(tc, 0, structSize);
+
+    TypeFieldCache *tfc = &tc->fields[0];
+    tc->fieldCount = fieldCount;
+    _env->SetIntField(_type, gTypeNativeCache, (jint)tc);
+
+    jint *fType = _env->GetIntArrayElements(_types, NULL);
+    jint *fBits = _env->GetIntArrayElements(_bits, NULL);
+    for (int ct=0; ct < fieldCount; ct++) {
+        jobject field = _env->GetObjectArrayElement(_IDs, ct);
+        tfc[ct].field = _env->FromReflectedField(field);
+        tfc[ct].bits = fBits[ct];
+
+        switch(fType[ct]) {
+        case RS_TYPE_FLOAT:
+            tfc[ct].ptr = SF_LoadFloat;
+            break;
+        case RS_TYPE_UNSIGNED:
+        case RS_TYPE_SIGNED:
+            switch(tfc[ct].bits) {
+            case 32:    tfc[ct].ptr = SF_LoadInt;   break;
+            case 16:    tfc[ct].ptr = SF_LoadShort; break;
+            case 8:     tfc[ct].ptr = SF_LoadByte;  break;
+            }
+            break;
+        }
+        tc->size += 4;
+    }
+
+    _env->ReleaseIntArrayElements(_types, fType, JNI_ABORT);
+    _env->ReleaseIntArrayElements(_bits, fBits, JNI_ABORT);
+}
+
+
 // -----------------------------------
 
 static jint
@@ -396,7 +492,7 @@
     jint len = _env->GetArrayLength(data);
     LOG_API("nAllocationRead_i, con(%p), alloc(%p), len(%i)", con, (RsAllocation)alloc, len);
     jint *ptr = _env->GetIntArrayElements(data, NULL);
-    rsAllocationData((RsAllocation)alloc, ptr);
+    rsAllocationRead((RsAllocation)alloc, ptr);
     _env->ReleaseIntArrayElements(data, ptr, JNI_COMMIT);
 }
 
@@ -405,13 +501,33 @@
 {
     RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
     jint len = _env->GetArrayLength(data);
-    LOG_API("nAllocationRead_i, con(%p), alloc(%p), len(%i)", con, (RsAllocation)alloc, len);
+    LOG_API("nAllocationRead_f, con(%p), alloc(%p), len(%i)", con, (RsAllocation)alloc, len);
     jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
-    rsAllocationData((RsAllocation)alloc, ptr);
+    rsAllocationRead((RsAllocation)alloc, ptr);
     _env->ReleaseFloatArrayElements(data, ptr, JNI_COMMIT);
 }
 
 
+//{"nAllocationDataFromObject",      "(ILandroid/renderscript/Type;Ljava/lang/Object;)V",   (void*)nAllocationDataFromObject },
+static void
+nAllocationDataFromObject(JNIEnv *_env, jobject _this, jint alloc, jobject _type, jobject _o)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nAllocationDataFromObject con(%p), alloc(%p)", con, (RsAllocation)alloc);
+
+    const TypeCache *tc = (TypeCache *)_env->GetIntField(_type, gTypeNativeCache);
+
+    void * bufAlloc = malloc(tc->size);
+    void * buf = bufAlloc;
+    for (int ct=0; ct < tc->fieldCount; ct++) {
+        const TypeFieldCache *tfc = &tc->fields[ct];
+        buf = tfc->ptr(_env, _o, tfc->field, buf);
+    }
+    rsAllocationData((RsAllocation)alloc, bufAlloc);
+    const uint32_t * tmp = (const uint32_t *)bufAlloc;
+    free(bufAlloc);
+}
+
 // -----------------------------------
 
 static void
@@ -708,6 +824,29 @@
     }
 }
 
+static void
+nScriptSetType(JNIEnv *_env, jobject _this, jint type, jstring _str, jint slot)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nScriptCAddType, con(%p), type(%p), slot(%i)", con, (RsType)type, slot);
+    const char* n = NULL;
+    if (_str) {
+        n = _env->GetStringUTFChars(_str, NULL);
+    }
+    rsScriptSetType((RsType)type, slot, n);
+    if (n) {
+        _env->ReleaseStringUTFChars(_str, n);
+    }
+}
+
+static void
+nScriptSetRoot(JNIEnv *_env, jobject _this, jboolean isRoot)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nScriptCSetRoot, con(%p), isRoot(%i)", con, isRoot);
+    rsScriptSetRoot(isRoot);
+}
+
 // -----------------------------------
 
 static void
@@ -719,22 +858,6 @@
 }
 
 static void
-nScriptCAddType(JNIEnv *_env, jobject _this, jint type)
-{
-    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
-    LOG_API("nScriptCAddType, con(%p), type(%p)", con, (RsType)type);
-    rsScriptCAddType((RsType)type);
-}
-
-static void
-nScriptCSetRoot(JNIEnv *_env, jobject _this, jboolean isRoot)
-{
-    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
-    LOG_API("nScriptCSetRoot, con(%p), isRoot(%i)", con, isRoot);
-    rsScriptCSetRoot(isRoot);
-}
-
-static void
 nScriptCSetScript(JNIEnv *_env, jobject _this, jbyteArray scriptRef,
                   jint offset, jint length)
 {
@@ -1195,7 +1318,7 @@
 
 {"nElementBegin",                  "()V",                                  (void*)nElementBegin },
 {"nElementAddPredefined",          "(I)V",                                 (void*)nElementAddPredefined },
-{"nElementAdd",                    "(IIII)V",                              (void*)nElementAdd },
+{"nElementAdd",                    "(IIIILjava/lang/String;)V",            (void*)nElementAdd },
 {"nElementCreate",                 "()I",                                  (void*)nElementCreate },
 {"nElementGetPredefined",          "(I)I",                                 (void*)nElementGetPredefined },
 {"nElementDestroy",                "(I)V",                                 (void*)nElementDestroy },
@@ -1204,6 +1327,8 @@
 {"nTypeAdd",                       "(II)V",                                (void*)nTypeAdd },
 {"nTypeCreate",                    "()I",                                  (void*)nTypeCreate },
 {"nTypeDestroy",                   "(I)V",                                 (void*)nTypeDestroy },
+{"nTypeFinalDestroy",              "(Landroid/renderscript/Type;)V",       (void*)nTypeFinalDestroy },
+{"nTypeSetupFields",               "(Landroid/renderscript/Type;[I[I[Ljava/lang/reflect/Field;)V", (void*)nTypeSetupFields },
 
 {"nAllocationCreateTyped",         "(I)I",                                 (void*)nAllocationCreateTyped },
 {"nAllocationCreatePredefSized",   "(II)I",                                (void*)nAllocationCreatePredefSized },
@@ -1220,6 +1345,7 @@
 {"nAllocationSubData2D",           "(IIIII[F)V",                           (void*)nAllocationSubData2D_f },
 {"nAllocationRead",                "(I[I)V",                               (void*)nAllocationRead_i },
 {"nAllocationRead",                "(I[F)V",                               (void*)nAllocationRead_f },
+{"nAllocationDataFromObject",      "(ILandroid/renderscript/Type;Ljava/lang/Object;)V",   (void*)nAllocationDataFromObject },
 
 {"nTriangleMeshDestroy",           "(I)V",                                 (void*)nTriangleMeshDestroy },
 {"nTriangleMeshBegin",             "(II)V",                                (void*)nTriangleMeshBegin },
@@ -1255,10 +1381,10 @@
 {"nScriptSetClearDepth",           "(IF)V",                                (void*)nScriptSetClearDepth },
 {"nScriptSetClearStencil",         "(II)V",                                (void*)nScriptSetClearStencil },
 {"nScriptSetTimeZone",             "(I[B)V",                               (void*)nScriptSetTimeZone },
+{"nScriptSetType",                 "(ILjava/lang/String;I)V",              (void*)nScriptSetType },
+{"nScriptSetRoot",                 "(Z)V",                                 (void*)nScriptSetRoot },
 
 {"nScriptCBegin",                  "()V",                                  (void*)nScriptCBegin },
-{"nScriptCAddType",                "(I)V",                                 (void*)nScriptCAddType },
-{"nScriptCSetRoot",                "(Z)V",                                 (void*)nScriptCSetRoot },
 {"nScriptCSetScript",              "([BII)V",                              (void*)nScriptCSetScript },
 {"nScriptCCreate",                 "()I",                                  (void*)nScriptCCreate },
 {"nScriptCAddDefineI32",           "(Ljava/lang/String;I)V",               (void*)nScriptCAddDefineI32 },
diff --git a/include/ui/Camera.h b/include/ui/Camera.h
index afb07b5..ae6e255 100644
--- a/include/ui/Camera.h
+++ b/include/ui/Camera.h
@@ -66,15 +66,16 @@
 
 // msgType in notifyCallback and dataCallback functions
 enum {
-    CAMERA_MSG_ERROR = 0,
-    CAMERA_MSG_SHUTTER,
-    CAMERA_MSG_FOCUS,
-    CAMERA_MSG_ZOOM,
-    CAMERA_MSG_PREVIEW_FRAME,
-    CAMERA_MSG_VIDEO_FRAME,
-    CAMERA_MSG_POSTVIEW_FRAME,
-    CAMERA_MSG_RAW_IMAGE,
-    CAMERA_MSG_COMPRESSED_IMAGE
+    CAMERA_MSG_ERROR            = 0x001,
+    CAMERA_MSG_SHUTTER          = 0x002,
+    CAMERA_MSG_FOCUS            = 0x004,
+    CAMERA_MSG_ZOOM             = 0x008,
+    CAMERA_MSG_PREVIEW_FRAME    = 0x010,
+    CAMERA_MSG_VIDEO_FRAME      = 0x020,
+    CAMERA_MSG_POSTVIEW_FRAME   = 0x040,
+    CAMERA_MSG_RAW_IMAGE        = 0x080,
+    CAMERA_MSG_COMPRESSED_IMAGE = 0x100,
+    CAMERA_MSG_ALL_MSGS         = 0x1FF
 };
 
 // camera fatal errors
diff --git a/include/ui/CameraHardwareInterface.h b/include/ui/CameraHardwareInterface.h
index c703f5e..535f70e 100644
--- a/include/ui/CameraHardwareInterface.h
+++ b/include/ui/CameraHardwareInterface.h
@@ -19,28 +19,26 @@
 
 #include <binder/IMemory.h>
 #include <utils/RefBase.h>
+#include <ui/ISurface.h>
+#include <ui/Camera.h>
 #include <ui/CameraParameters.h>
 #include <ui/Overlay.h>
 
 namespace android {
 
-/** Callback for startPreview() */
-typedef void (*preview_callback)(const sp<IMemory>& mem, void* user);
+typedef void (*notify_callback)(int32_t msgType,
+                                int32_t ext1,
+                                int32_t ext2,
+                                void* user);
 
-/** Callback for startRecord() */
-typedef void (*recording_callback)(nsecs_t timestamp, const sp<IMemory>& mem, void* user);
+typedef void (*data_callback)(int32_t msgType,
+                              const sp<IMemory>& dataPtr,
+                              void* user);
 
-/** Callback for takePicture() */
-typedef void (*shutter_callback)(void* user);
-
-/** Callback for takePicture() */
-typedef void (*raw_callback)(const sp<IMemory>& mem, void* user);
-
-/** Callback for takePicture() */
-typedef void (*jpeg_callback)(const sp<IMemory>& mem, void* user);
-
-/** Callback for autoFocus() */
-typedef void (*autofocus_callback)(bool focused, void* user);
+typedef void (*data_callback_timestamp)(nsecs_t timestamp,
+                                        int32_t msgType,
+                                        const sp<IMemory>& dataPtr,
+                                        void* user);
 
 /**
  * CameraHardwareInterface.h defines the interface to the
@@ -57,28 +55,21 @@
  *      CameraService calls getPreviewHeap() to establish access to the
  *      preview heap so it can be registered with SurfaceFlinger for
  *      efficient display updating while in preview mode.
- *   -# startPreview() is called, which is passed a preview_callback()
- *      function and a user parameter. The camera instance then periodically
- *      calls preview_callback() each time a new preview frame is available.
- *      The callback routine has two parameters: the first is a pointer to
- *      the IMemory containing the frame and the second a user parameter. If
- *      the preview_callback code needs to use this memory after returning,
- *      it must copy the data.
+ *   -# startPreview() is called.  The camera instance then periodically
+ *      sends the message CAMERA_MSG_PREVIEW_FRAME (if enabled) each time
+ *      a new preview frame is available.  If data callback code needs to use
+ *      this memory after returning, it must copy the data.
  *
- * Prior to taking a picture, CameraService calls autofocus() with
- * autofocus_callback() and a user parameter. When auto focusing has
- * completed, the camera instance calls autofocus_callback(), which informs
- * the application whether focusing was successful. The camera instance
- * only calls autofocus_callback() once and it is up to the application to
- * call autoFocus() again if refocusing is desired.
+ * Prior to taking a picture, CameraService calls autofocus(). When auto
+ * focusing has completed, the camera instance sends a CAMERA_MSG_FOCUS notification,
+ * which informs the application whether focusing was successful. The camera instance
+ * only sends this message once and it is up  to the application to call autoFocus()
+ * again if refocusing is desired.
  *
  * CameraService calls takePicture() to request the camera instance take a
- * picture. This method has two callbacks: raw_callback() and jpeg_callback().
- * When the raw image is available, raw_callback() is called with a pointer
- * to the IMemory containing the raw image. When the jpeg image is available,
- * jpeg_callback() is called with a pointer to the IMemory containing the
- * jpeg image. As with preview_callback(), the memory must be copied if it's
- * needed after returning.
+ * picture. At this point, if a shutter, postview, raw, and/or compressed callback
+ * is desired, the corresponding message must be enabled. As with CAMERA_MSG_PREVIEW_FRAME,
+ * any memory provided in a data callback must be copied if it's needed after returning.
  */
 class CameraHardwareInterface : public virtual RefBase {
 public:
@@ -90,17 +81,45 @@
     /** Return the IMemoryHeap for the raw image heap */
     virtual sp<IMemoryHeap>         getRawHeap() const = 0;
 
+    /** Set the notification and data callbacks */
+    virtual void setCallbacks(notify_callback notify_cb,
+                              data_callback data_cb,
+                              data_callback_timestamp data_cb_timestamp,
+                              void* user) = 0;
+
     /**
-     * Start preview mode. When a preview image is available
-     * preview_callback is called with the user parameter. The
-     * call back parameter may be null.
+     * The following three functions all take a msgtype,
+     * which is a bitmask of the messages defined in
+     * include/ui/Camera.h
      */
-    virtual status_t    startPreview(preview_callback cb, void* user) = 0;
+
+    /**
+     * Enable a message, or set of messages.
+     */
+    virtual void        enableMsgType(int32_t msgType) = 0;
+
+    /**
+     * Disable a message, or a set of messages.
+     */
+    virtual void        disableMsgType(int32_t msgType) = 0;
+
+    /**
+     * Query whether a message, or a set of messages, is enabled.
+     * Note that this is operates as an AND, if any of the messages
+     * queried are off, this will return false.
+     */
+    virtual bool        msgTypeEnabled(int32_t msgType) = 0;
+
+    /**
+     * Start preview mode.
+     */
+    virtual status_t    startPreview() = 0;
+
     /**
      * Only used if overlays are used for camera preview.
      */
-    virtual bool useOverlay() {return false;}
-    virtual status_t setOverlay(const sp<Overlay> &overlay) {return BAD_VALUE;}
+    virtual bool         useOverlay() {return false;}
+    virtual status_t     setOverlay(const sp<Overlay> &overlay) {return BAD_VALUE;}
 
     /**
      * Stop a previously started preview.
@@ -113,11 +132,11 @@
     virtual bool        previewEnabled() = 0;
 
     /**
-     * Start record mode. When a record image is available recording_callback()
-     * is called with the user parameter.  Every record frame must be released
+     * Start record mode. When a record image is available a CAMERA_MSG_VIDEO_FRAME
+     * message is sent with the corresponding frame. Every record frame must be released
      * by calling releaseRecordingFrame().
      */
-    virtual status_t    startRecording(recording_callback cb, void* user) = 0;
+    virtual status_t    startRecording() = 0;
 
     /**
      * Stop a previously started recording.
@@ -130,39 +149,27 @@
     virtual bool        recordingEnabled() = 0;
     
     /**
-     * Release a record frame previously returned by the recording_callback()
-     * passed to startRecord().
+     * Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME.
      */
     virtual void        releaseRecordingFrame(const sp<IMemory>& mem) = 0;
 
     /**
-     * Start auto focus, the callback routine is called
-     * once when focusing is complete. autoFocus() will
-     * be called again if another auto focus is needed.
+     * Start auto focus, the notification callback routine is called
+     * with CAMERA_MSG_FOCUS once when focusing is complete. autoFocus()
+     * will be called again if another auto focus is needed.
      */
-    virtual status_t    autoFocus(autofocus_callback,
-                                  void* user) = 0;
+    virtual status_t    autoFocus() = 0;
 
     /**
-     * Take a picture. The raw_callback is called when
-     * the uncompressed image is available. The jpeg_callback
-     * is called when the compressed image is available. These
-     * call backs may be null. The user parameter is passed
-     * to each of the call back routines.
+     * Take a picture.
      */
-    virtual status_t    takePicture(shutter_callback,
-                                    raw_callback,
-                                    jpeg_callback,
-                                    void* user) = 0;
+    virtual status_t    takePicture() = 0;
 
     /**
-     * Cancel a picture that was started with takePicture.  You may cancel any
-     * of the shutter, raw, or jpeg callbacks.  Calling this method when no
-     * picture is being taken is a no-op.
+     * Cancel a picture that was started with takePicture.  Calling this
+     * method when no picture is being taken is a no-op.
      */
-    virtual status_t    cancelPicture(bool cancel_shutter,
-                                      bool cancel_raw,
-                                      bool cancel_jpeg) = 0;
+    virtual status_t    cancelPicture() = 0;
 
     /** Set the camera parameters. */
     virtual status_t    setParameters(const CameraParameters& params) = 0;
diff --git a/include/ui/FramebufferNativeWindow.h b/include/ui/FramebufferNativeWindow.h
index cb9bf94..68144b5 100644
--- a/include/ui/FramebufferNativeWindow.h
+++ b/include/ui/FramebufferNativeWindow.h
@@ -63,6 +63,7 @@
     static int lockBuffer(android_native_window_t* window, android_native_buffer_t* buffer);
     static int queueBuffer(android_native_window_t* window, android_native_buffer_t* buffer);
     static int query(android_native_window_t* window, int what, int* value);
+    static int perform(android_native_window_t* window, int operation, ...);
     
     framebuffer_device_t* fbDev;
     alloc_device_t* grDev;
diff --git a/include/ui/ISurface.h b/include/ui/ISurface.h
index adba45a..7909c2f 100644
--- a/include/ui/ISurface.h
+++ b/include/ui/ISurface.h
@@ -50,7 +50,7 @@
 public: 
     DECLARE_META_INTERFACE(Surface);
 
-    virtual sp<SurfaceBuffer> getBuffer() = 0; 
+    virtual sp<SurfaceBuffer> getBuffer(int usage) = 0; 
     
     class BufferHeap {
     public:
diff --git a/include/ui/Surface.h b/include/ui/Surface.h
index d5dad31..4ff0e4a 100644
--- a/include/ui/Surface.h
+++ b/include/ui/Surface.h
@@ -184,7 +184,7 @@
     friend class IOMX;
     const sp<ISurface>& getISurface() const { return mSurface; }
 
-    status_t getBufferLocked(int index);
+    status_t getBufferLocked(int index, int usage);
    
            status_t validate(per_client_cblk_t const* cblk) const;
     static void _send_dirty_region(layer_cblk_t* lcblk, const Region& dirty);
@@ -197,11 +197,13 @@
     static int lockBuffer(android_native_window_t* window, android_native_buffer_t* buffer);
     static int queueBuffer(android_native_window_t* window, android_native_buffer_t* buffer);
     static int query(android_native_window_t* window, int what, int* value);
+    static int perform(android_native_window_t* window, int operation, ...);
 
     int dequeueBuffer(android_native_buffer_t** buffer);
     int lockBuffer(android_native_buffer_t* buffer);
     int queueBuffer(android_native_buffer_t* buffer);
     int query(int what, int* value);
+    int perform(int operation, va_list args);
 
     status_t dequeueBuffer(sp<SurfaceBuffer>* buffer);
     status_t lockBuffer(const sp<SurfaceBuffer>& buffer);
@@ -217,6 +219,7 @@
     uint32_t                    mIdentity;
     uint32_t                    mWidth;
     uint32_t                    mHeight;
+    uint32_t                    mUsage;
     PixelFormat                 mFormat;
     uint32_t                    mFlags;
     mutable Region              mDirtyRegion;
diff --git a/include/ui/egl/android_natives.h b/include/ui/egl/android_natives.h
index 7da69b1..4c58e47 100644
--- a/include/ui/egl/android_natives.h
+++ b/include/ui/egl/android_natives.h
@@ -67,6 +67,11 @@
     NATIVE_WINDOW_FORMAT    = 2,
 };
 
+/* valid operations for the (*perform)() hook */
+enum {
+    NATIVE_WINDOW_SET_USAGE = 0
+};
+
 struct android_native_window_t 
 {
 #ifdef __cplusplus
@@ -142,11 +147,45 @@
      * Returns 0 on success or -errno on error.
      */
     int     (*query)(struct android_native_window_t* window,
-            int what, int* value);
+                int what, int* value);
     
-    void* reserved_proc[4];
+    /*
+     * hook used to perform various operations on the surface.
+     * (*perform)() is a generic mechanism to add functionality to
+     * android_native_window_t while keeping backward binary compatibility.
+     * 
+     * This hook should not be called directly, instead use the helper functions
+     * defined below.
+     * 
+     * The valid operations are:
+     *     NATIVE_WINDOW_SET_USAGE
+     *  
+     */
+    
+    int     (*perform)(struct android_native_window_t* window,
+                int operation, ... );
+    
+    void* reserved_proc[3];
 };
 
+
+/*
+ *  native_window_set_usage() sets the intended usage flags for the next
+ *  buffers acquired with (*lockBuffer)() and on.
+ *  By default (if this function is never called), a usage of
+ *      GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE
+ *  is assumed.
+ *  Calling this function will usually cause following buffers to be
+ *  reallocated.
+ */
+
+inline int native_window_set_usage(
+        struct android_native_window_t* window, int usage)
+{
+    return window->perform(window, NATIVE_WINDOW_SET_USAGE, usage);
+}
+
+
 // ---------------------------------------------------------------------------
 
 /* FIXME: this is legacy for pixmaps */
diff --git a/include/utils/Asset.h b/include/utils/Asset.h
index 453a204..5908bcc 100644
--- a/include/utils/Asset.h
+++ b/include/utils/Asset.h
@@ -45,6 +45,7 @@
     virtual ~Asset(void);
 
     static int32_t getGlobalCount();
+    static String8 getAssetAllocations();
     
     /* used when opening an asset */
     typedef enum AccessMode {
@@ -110,6 +111,12 @@
     virtual int openFileDescriptor(off_t* outStart, off_t* outLength) const = 0;
     
     /*
+     * Return whether this asset's buffer is allocated in RAM (not mmapped).
+     * Note: not virtual so it is safe to call even when being destroyed.
+     */
+    virtual bool isAllocated(void) const { return false; }
+    
+    /*
      * Get a string identifying the asset's source.  This might be a full
      * path, it might be a colon-separated list of identifiers.
      *
@@ -197,6 +204,9 @@
 
     AccessMode  mAccessMode;        // how the asset was opened
     String8    mAssetSource;       // debug string
+    
+    Asset*		mNext;				// linked list.
+    Asset*		mPrev;
 };
 
 
@@ -239,6 +249,7 @@
     virtual off_t getLength(void) const { return mLength; }
     virtual off_t getRemainingLength(void) const { return mLength-mOffset; }
     virtual int openFileDescriptor(off_t* outStart, off_t* outLength) const;
+    virtual bool isAllocated(void) const { return mBuf != NULL; }
 
 private:
     off_t       mStart;         // absolute file offset of start of chunk
@@ -295,6 +306,7 @@
     virtual off_t getLength(void) const { return mUncompressedLen; }
     virtual off_t getRemainingLength(void) const { return mUncompressedLen-mOffset; }
     virtual int openFileDescriptor(off_t* outStart, off_t* outLength) const { return -1; }
+    virtual bool isAllocated(void) const { return mBuf != NULL; }
 
 private:
     off_t       mStart;         // offset to start of compressed data
diff --git a/libs/audioflinger/A2dpAudioInterface.cpp b/libs/audioflinger/A2dpAudioInterface.cpp
index 20db8a5..57a29f2 100644
--- a/libs/audioflinger/A2dpAudioInterface.cpp
+++ b/libs/audioflinger/A2dpAudioInterface.cpp
@@ -204,7 +204,7 @@
     mFd(-1), mStandby(true), mStartCount(0), mRetryCount(0), mData(NULL),
     // assume BT enabled to start, this is safe because its only the
     // enabled->disabled transition we are worried about
-    mBluetoothEnabled(true), mDevice(0)
+    mBluetoothEnabled(true), mDevice(0), mClosing(false)
 {
     // use any address by default
     strcpy(mA2dpAddress, "00:00:00:00:00:00");
@@ -258,7 +258,7 @@
     size_t remaining = bytes;
     status_t status = -1;
 
-    if (!mBluetoothEnabled) {
+    if (!mBluetoothEnabled || mClosing) {
         LOGW("A2dpAudioStreamOut::write(), but bluetooth disabled");
         goto Error;
     }
@@ -307,6 +307,11 @@
 {
     int result = 0;
 
+    if (mClosing) {
+        LOGV("Ignore standby, closing");
+        return result;
+    }
+
     Mutex::Autolock lock(mLock);
 
     if (!mStandby) {
@@ -335,6 +340,11 @@
         }
         param.remove(key);
     }
+    key = String8("closing");
+    if (param.get(key, value) == NO_ERROR) {
+        mClosing = (value == "true");
+        param.remove(key);
+    }
     key = AudioParameter::keyRouting;
     if (param.getInt(key, device) == NO_ERROR) {
         if (AudioSystem::isA2dpDevice((AudioSystem::audio_devices)device)) {
diff --git a/libs/audioflinger/A2dpAudioInterface.h b/libs/audioflinger/A2dpAudioInterface.h
index d6709e2..35a6e11 100644
--- a/libs/audioflinger/A2dpAudioInterface.h
+++ b/libs/audioflinger/A2dpAudioInterface.h
@@ -112,6 +112,7 @@
                 Mutex       mLock;
                 bool        mBluetoothEnabled;
                 uint32_t    mDevice;
+                bool        mClosing;
     };
 
     friend class A2dpAudioStreamOut;
diff --git a/libs/rs/Android.mk b/libs/rs/Android.mk
index 7075842..bc466be 100644
--- a/libs/rs/Android.mk
+++ b/libs/rs/Android.mk
@@ -26,6 +26,7 @@
 
 
 # Build render script lib ====================
+
 include $(CLEAR_VARS)
 LOCAL_MODULE := libRS
 
@@ -67,6 +68,11 @@
 
 LOCAL_GENERATED_SOURCES += $(GEN)
 
+# libRS needs libacc, which isn't 64-bit clean, and so can't be built
+# for the simulator on gHardy, and therefore libRS needs to be excluded
+# from the simulator as well.
+ifneq ($(TARGET_SIMULATOR),true)
+
 LOCAL_SRC_FILES:= \
 	rsAdapter.cpp \
 	rsAllocation.cpp \
@@ -106,3 +112,4 @@
             java \
     	))
 
+endif #simulator
diff --git a/libs/rs/java/Film/res/raw/filmstrip.c b/libs/rs/java/Film/res/raw/filmstrip.c
index 4e7c37a..255d908 100644
--- a/libs/rs/java/Film/res/raw/filmstrip.c
+++ b/libs/rs/java/Film/res/raw/filmstrip.c
@@ -22,8 +22,8 @@
 {
     float mat1[16];
 
-    float trans = loadF(1, POS_TRANSLATE);
-    float rot = loadF(1, POS_ROTATE);
+    float trans = Pos_translate;
+    float rot = Pos_rotate;
     matrixLoadScale(mat1, 2.f, 2.f, 2.f);
     matrixTranslate(mat1, 0.f, 0.f, trans);
     matrixRotate(mat1, 90.f, 0.f, 0.f, 1.f);
@@ -39,7 +39,7 @@
     bindProgramFragment(NAMED_PFImages);
     bindProgramVertex(NAMED_PVImages);
 
-    float focusPos = loadF(1, POS_FOCUS);
+    float focusPos = Pos_focus;
     int focusID = 0;
     int lastFocusID = loadI32(2, STATE_LAST_FOCUS);
     int imgCount = 13;
@@ -65,7 +65,7 @@
     */
     storeI32(2, STATE_LAST_FOCUS, focusID);
 
-    int triangleOffsetsCount = loadI32(2, STATE_TRIANGLE_OFFSET_COUNT);
+    int triangleOffsetsCount = Pos_triangleOffsetCount;
 
     int imgId = 0;
     for (imgId=1; imgId <= imgCount; imgId++) {
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 74f88c4..e6cd52d 100644
--- a/libs/rs/java/Film/src/com/android/film/FilmRS.java
+++ b/libs/rs/java/Film/src/com/android/film/FilmRS.java
@@ -23,25 +23,18 @@
 import android.graphics.Bitmap;
 import android.util.Log;
 
-import android.renderscript.Matrix;
-import android.renderscript.ProgramVertex;
-import android.renderscript.RenderScript;
-import android.renderscript.Element;
-import android.renderscript.Allocation;
-import android.renderscript.Dimension;
-import android.renderscript.ScriptC;
-import android.renderscript.Script;
-import android.renderscript.ProgramFragment;
-import android.renderscript.ProgramStore;
-import android.renderscript.Sampler;
-import android.renderscript.Light;
+import android.renderscript.*;
 
 public class FilmRS {
-    private final int POS_TRANSLATE = 0;
-    private final int POS_ROTATE = 1;
-    private final int POS_FOCUS = 2;
+    class StripPosition {
+        public float translate;
+        public float rotate;
+        public float focus;
+        public int triangleOffsetCount;
+    }
+    StripPosition mPos = new StripPosition();
 
-    private final int STATE_TRIANGLE_OFFSET_COUNT = 0;
+
     private final int STATE_LAST_FOCUS = 1;
 
     public FilmRS() {
@@ -63,10 +56,11 @@
         }
 
         float anim = ((float)x-50) / 270.f;
-        mBufferPos[POS_TRANSLATE] = 2f * anim + 0.5f;   // translation
-        mBufferPos[POS_ROTATE] = (anim * 40);  // rotation
-        mBufferPos[POS_FOCUS] = ((float)y) / 16.f - 10.f;  // focusPos
-        mAllocPos.data(mBufferPos);
+        mPos.translate = 2f * anim + 0.5f;   // translation
+        mPos.rotate = (anim * 40);  // rotation
+        mPos.focus = ((float)y) / 16.f - 10.f;  // focusPos
+        mPos.triangleOffsetCount = mFSM.mTriangleOffsetsCount;
+        mAllocPos.data(mPos);
     }
 
 
@@ -84,6 +78,7 @@
     private ProgramVertex mPVBackground;
     private ProgramVertex mPVImages;
     private ProgramVertex.MatrixAllocation mPVA;
+    private Type mStripPositionType;
 
     private Allocation mImages[];
     private Allocation mAllocIDs;
@@ -204,10 +199,7 @@
         mBufferState = new int[10];
         mAllocState = Allocation.createSized(mRS,
             Element.USER_FLOAT, mBufferState.length);
-
-        mBufferState[STATE_TRIANGLE_OFFSET_COUNT] = mFSM.mTriangleOffsetsCount;
         mBufferState[STATE_LAST_FOCUS] = -1;
-
         mAllocState.data(mBufferState);
     }
 
@@ -227,14 +219,16 @@
 
         Log.e("rs", "Done loading named");
 
+        mStripPositionType = Type.createFromClass(mRS, StripPosition.class, 1);
+
         ScriptC.Builder sb = new ScriptC.Builder(mRS);
         sb.setScript(mRes, R.raw.filmstrip);
         sb.setRoot(true);
+        sb.setType(mStripPositionType, "Pos", 1);
         mScriptStrip = sb.create();
         mScriptStrip.setClearColor(0.0f, 0.0f, 0.0f, 1.0f);
 
-        mAllocPos = Allocation.createSized(mRS,
-            Element.USER_FLOAT, mBufferPos.length);
+        mAllocPos = Allocation.createTyped(mRS, mStripPositionType);
 
         loadImages();
         initState();
diff --git a/libs/rs/java/Fountain/res/raw/fountain.c b/libs/rs/java/Fountain/res/raw/fountain.c
index 5ed9ed51..6e6afcd 100644
--- a/libs/rs/java/Fountain/res/raw/fountain.c
+++ b/libs/rs/java/Fountain/res/raw/fountain.c
@@ -7,38 +7,23 @@
 
 
 int main(int launchID) {
-    int count, touch, x, y, rate;
-    int ct, ct2;
-    int newPart;
-    int drawCount;
-    int idx;
-    float dx, dy;
-    float posx,posy;
-    int c;
-    int srcIdx;
-    int dstIdx;
-
-    count = loadI32(0, 1);
-    touch = loadI32(0, 2);
-    x = loadI32(0, 3);
-    y = loadI32(0, 4);
-
-    rate = 4;
+    int ct;
+    int count = loadI32(0, OFFSETOF_SomeData_count);
+    int touch = loadI32(0, OFFSETOF_SomeData_touch);
+    int rate = 4;
     int maxLife = (count / rate) - 1;
 
     if (touch) {
-        newPart = loadI32(2, 0);
-        for (ct2=0; ct2<rate; ct2++) {
-            dx = randf(1.f) - 0.5f;
-            dy = randf(1.f) - 0.5f;
-
-            idx = newPart * 5 + 1;
-            storeF(2, idx, dx);
-            storeF(2, idx + 1, dy);
+        int x = loadI32(0, OFFSETOF_SomeData_x);
+        int y = loadI32(0, OFFSETOF_SomeData_y);
+        int newPart = loadI32(2, 0);
+        for (ct=0; ct<rate; ct++) {
+            int idx = newPart * 5 + 1;
+            storeF(2, idx, randf(1.f) - 0.5f);
+            storeF(2, idx + 1, randf(1.f) - 0.5f);
             storeI32(2, idx + 2, maxLife);
             storeF(2, idx + 3, x);
             storeF(2, idx + 4, y);
-
             newPart++;
             if (newPart >= count) {
                 newPart = 0;
@@ -47,21 +32,21 @@
         storeI32(2, 0, newPart);
     }
 
-    drawCount = 0;
+    int drawCount = 0;
     float height = getHeight();
     for (ct=0; ct < count; ct++) {
-        srcIdx = ct * 5 + 1;
+        int srcIdx = ct * 5 + 1;
 
-        dx = loadF(2, srcIdx);
-        dy = loadF(2, srcIdx + 1);
         int life = loadI32(2, srcIdx + 2);
-        posx = loadF(2, srcIdx + 3);
-        posy = loadF(2, srcIdx + 4);
 
         if (life) {
+            float posx = loadF(2, srcIdx + 3);
+            float posy = loadF(2, srcIdx + 4);
+            float dx = loadF(2, srcIdx);
+            float dy = loadF(2, srcIdx + 1);
             if (posy < height) {
-                dstIdx = drawCount * 9;
-                c = 0xcfcfcfcf;
+                int dstIdx = drawCount * 9;
+                int c = 0xcfcfcfcf;
 
                 storeI32(1, dstIdx, c);
                 storeF(1, dstIdx + 1, posx);
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 ad4f949..da4eeb4 100644
--- a/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
+++ b/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java
@@ -23,24 +23,21 @@
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
+import android.renderscript.*;
 import android.util.Log;
 
-import android.renderscript.RenderScript;
-import android.renderscript.ProgramVertex;
-import android.renderscript.Element;
-import android.renderscript.Allocation;
-import android.renderscript.Script;
-import android.renderscript.ScriptC;
-import android.renderscript.ProgramFragment;
-import android.renderscript.ProgramStore;
-import android.renderscript.SimpleMesh;
-import android.renderscript.Type;
-import android.renderscript.Primitive;
-
 
 public class FountainRS {
     public static final int PART_COUNT = 4000;
 
+    static class SomeData {
+        public int x;
+        public int y;
+        public int touch;
+        public int rate;
+        public int count;
+    }
+
     public FountainRS() {
     }
 
@@ -51,10 +48,10 @@
     }
 
     public void newTouchPosition(int x, int y) {
-        mParams[0] = 1;
-        mParams[1] = x;
-        mParams[2] = y;
-        mIntAlloc.subData1D(2, 3, mParams);
+        mSD.touch = 1;
+        mSD.x = x;
+        mSD.y = y;
+        mIntAlloc.data(mSD);
     }
 
 
@@ -73,10 +70,13 @@
 
     private Bitmap mBackground;
 
-    int mParams[] = new int[10];
+    SomeData mSD = new SomeData();
+    private Type mSDType;
 
     private void initRS() {
-        mIntAlloc = Allocation.createSized(mRS, Element.USER_I32, 10);
+        mSD = new SomeData();
+        mSDType = Type.createFromClass(mRS, SomeData.class, 1, "SomeData");
+        mIntAlloc = Allocation.createTyped(mRS, mSDType);
         mVertAlloc = Allocation.createSized(mRS, Element.USER_I32, PART_COUNT * 5 + 1);
 
         ProgramStore.Builder bs = new ProgramStore.Builder(mRS, null, null);
@@ -91,14 +91,8 @@
         mPF = bf.create();
         mPF.setName("PgmFragParts");
 
-        mParams[0] = 0;
-        mParams[1] = PART_COUNT;
-        mParams[2] = 0;
-        mParams[3] = 0;
-        mParams[4] = 0;
-        mParams[5] = 0;
-        mParams[6] = 0;
-        mIntAlloc.data(mParams);
+        mSD.count = PART_COUNT;
+        mIntAlloc.data(mSD);
 
         Element.Builder eb = new Element.Builder(mRS);
         eb.add(Element.DataType.UNSIGNED, Element.DataKind.RED, true, 8);
@@ -124,6 +118,7 @@
         ScriptC.Builder sb = new ScriptC.Builder(mRS);
         sb.setScript(mRes, R.raw.fountain);
         sb.setRoot(true);
+        sb.setType(mSDType, 0);
         mScript = sb.create();
         mScript.setClearColor(0.0f, 0.0f, 0.0f, 1.0f);
 
diff --git a/libs/rs/java/Grass/Android.mk b/libs/rs/java/Grass/Android.mk
deleted file mode 100644
index ce5294e..0000000
--- a/libs/rs/java/Grass/Android.mk
+++ /dev/null
@@ -1,25 +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.
-#
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-#LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript
-
-LOCAL_PACKAGE_NAME := GrassRS
-
-include $(BUILD_PACKAGE)
diff --git a/libs/rs/java/Grass/AndroidManifest.xml b/libs/rs/java/Grass/AndroidManifest.xml
deleted file mode 100644
index a40f378..0000000
--- a/libs/rs/java/Grass/AndroidManifest.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.grass.rs">
-
-    <application android:label="GrassRS">
-
-        <activity
-            android:name="Grass"
-            android:theme="@android:style/Theme.NoTitleBar">
-
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-
-        </activity>
-
-    </application>
-
-</manifest>
diff --git a/libs/rs/java/Grass/res/drawable-hdpi/night.jpg b/libs/rs/java/Grass/res/drawable-hdpi/night.jpg
deleted file mode 100644
index 77cd7f4..0000000
--- a/libs/rs/java/Grass/res/drawable-hdpi/night.jpg
+++ /dev/null
Binary files differ
diff --git a/libs/rs/java/Grass/res/drawable-hdpi/sky.jpg b/libs/rs/java/Grass/res/drawable-hdpi/sky.jpg
deleted file mode 100644
index a12fe20..0000000
--- a/libs/rs/java/Grass/res/drawable-hdpi/sky.jpg
+++ /dev/null
Binary files differ
diff --git a/libs/rs/java/Grass/res/drawable-hdpi/sunrise.jpg b/libs/rs/java/Grass/res/drawable-hdpi/sunrise.jpg
deleted file mode 100644
index db016b2..0000000
--- a/libs/rs/java/Grass/res/drawable-hdpi/sunrise.jpg
+++ /dev/null
Binary files differ
diff --git a/libs/rs/java/Grass/res/drawable-hdpi/sunset.jpg b/libs/rs/java/Grass/res/drawable-hdpi/sunset.jpg
deleted file mode 100644
index 49bb0c6..0000000
--- a/libs/rs/java/Grass/res/drawable-hdpi/sunset.jpg
+++ /dev/null
Binary files differ
diff --git a/libs/rs/java/Grass/res/raw/grass.c b/libs/rs/java/Grass/res/raw/grass.c
deleted file mode 100644
index 1490012..0000000
--- a/libs/rs/java/Grass/res/raw/grass.c
+++ /dev/null
@@ -1,202 +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.
-
-#pragma version(1)
-#pragma stateVertex(PVBackground)
-#pragma stateFragment(PFBackground)
-#pragma stateFragmentStore(PFSBackground)
-
-#define RSID_STATE 0
-#define RSID_FRAME_COUNT 0
-#define RSID_BLADES_COUNT 1
-#define RSID_WIDTH 2
-#define RSID_HEIGHT 3
-
-#define RSID_BLADES 1
-#define BLADE_STRUCT_FIELDS_COUNT 12
-#define BLADE_STRUCT_ANGLE 0
-#define BLADE_STRUCT_SIZE 1
-#define BLADE_STRUCT_XPOS 2
-#define BLADE_STRUCT_YPOS 3
-#define BLADE_STRUCT_OFFSET 4
-#define BLADE_STRUCT_SCALE 5
-#define BLADE_STRUCT_LENGTHX 6
-#define BLADE_STRUCT_LENGTHY 7
-#define BLADE_STRUCT_HARDNESS 8
-#define BLADE_STRUCT_H 9
-#define BLADE_STRUCT_S 10
-#define BLADE_STRUCT_B 11
-
-#define TESSELATION 2.0f
-
-#define MAX_BEND 0.09f
-
-#define MIDNIGHT 0.0f
-#define MORNING 0.375f
-#define AFTERNOON 0.6f
-#define DUSK 0.8f
-
-#define SECONDS_IN_DAY 24.0f * 3600.0f
-
-#define PI 3.1415926f
-
-#define REAL_TIME 0
-
-float time(int frameCount) {
-    if (REAL_TIME) {
-        return (hour() * 3600.0f + minute() * 60.0f + second()) / SECONDS_IN_DAY;
-    }
-    return (frameCount % 180) / 180.0f;
-}
-
-void alpha(float a) {
-    color(1.0f, 1.0f, 1.0f, a);
-}
-
-void drawNight(int width, int height) {
-    bindTexture(NAMED_PFBackground, 0, NAMED_TNight);
-    drawRect(width - 512.0f, -32.0f, width, 1024.0f - 32.0f, 0.0f);
-}
-
-void drawSunrise(int width, int height) {
-    bindTexture(NAMED_PFBackground, 0, NAMED_TSunrise);
-    drawRect(0.0f, 0.0f, width, height, 0.0f);
-}
-
-void drawNoon(int width, int height) {
-    bindTexture(NAMED_PFBackground, 0, NAMED_TSky);
-    drawRect(0.0f, 0.0f, width, height, 0.0f);
-}
-
-void drawSunset(int width, int height) {
-    bindTexture(NAMED_PFBackground, 0, NAMED_TSunset);
-    drawRect(0.0f, 0.0f, width, height, 0.0f);
-}
-
-void drawBlade(int index, float now, int frameCount) {
-    float *bladeStruct = loadArrayF(RSID_BLADES, index);
-    float offset = bladeStruct[BLADE_STRUCT_OFFSET];
-    float scale = bladeStruct[BLADE_STRUCT_SCALE];
-    float angle = bladeStruct[BLADE_STRUCT_ANGLE];
-    float hardness = bladeStruct[BLADE_STRUCT_HARDNESS];
-    
-    float xpos = bladeStruct[BLADE_STRUCT_XPOS];
-    float ypos = bladeStruct[BLADE_STRUCT_YPOS];
-
-    float lengthX = bladeStruct[BLADE_STRUCT_LENGTHX];
-    float lengthY = bladeStruct[BLADE_STRUCT_LENGTHY];
-
-    int size = bladeStruct[BLADE_STRUCT_SIZE];
-
-    float h = bladeStruct[BLADE_STRUCT_H];
-    float s = bladeStruct[BLADE_STRUCT_S];
-    float b = bladeStruct[BLADE_STRUCT_B];
-
-    float newB = 1.0f;
-    if (now >= MIDNIGHT && now < MORNING) {
-        newB = now / MORNING;
-    }
-
-    if (now >= AFTERNOON && now < DUSK) {
-        newB = 1.0f - normf(AFTERNOON, DUSK, now);
-    }
-
-    if (now >= DUSK) {
-        newB = 0.0f;
-    }
-
-    hsb(h, s, lerpf(0, b, newB), 1.0f);
-
-    float newAngle = turbulencef2(xpos * 0.006f, frameCount * 0.006f, 4.0f) - 0.5f;
-    newAngle /= 2.0f;
-    angle = clampf(angle + (newAngle + offset - angle) * 0.15f, -MAX_BEND, MAX_BEND);
-
-    float currentAngle = PI / 2.0f;
-
-    float bottomX = xpos;
-    float bottomY = ypos;
-
-    int i = size * TESSELATION;
-    float lx = lengthX / TESSELATION;
-    float ly = lengthY / TESSELATION;
-    float ss = 4.0f / i + scale / TESSELATION;
-    float sh = 0.5f / TESSELATION;
-    float d = angle * hardness / TESSELATION;
-
-    for ( ; i > 0; i--) {
-        float topX = bottomX - cosf(currentAngle) * size * lx;
-        float topY = bottomY - sinf(currentAngle) * size * ly;
-        currentAngle += d;
-
-        float spi = (i - 1) * ss;
-        float si = i * ss;
-
-        drawQuad(topX + spi, topY, 0.0f,
-                 topX - spi, topY, 0.0f,
-                 bottomX - si, bottomY + sh, 0.0f,
-                 bottomX + si, bottomY + sh, 0.0f);
-
-        bottomX = topX;
-        bottomY = topY;
-    }
-
-    storeF(RSID_BLADES, index + BLADE_STRUCT_ANGLE, angle);
-}
-
-void drawBlades(float now, int frameCount) {
-    // For anti-aliasing
-    bindTexture(NAMED_PFBackground, 0, NAMED_TAa);
-
-    int bladesCount = loadI32(RSID_STATE, RSID_BLADES_COUNT);
-    int count = bladesCount * BLADE_STRUCT_FIELDS_COUNT;
-
-    int i = 0;
-    for ( ; i < count; i += BLADE_STRUCT_FIELDS_COUNT) {
-        drawBlade(i, now, frameCount);
-    }
-}
-
-int main(int launchID) {
-    int width = loadI32(RSID_STATE, RSID_WIDTH);
-    int height = loadI32(RSID_STATE, RSID_HEIGHT);
-
-    int frameCount = loadI32(RSID_STATE, RSID_FRAME_COUNT);
-    float now = time(frameCount);
-    alpha(1.0f);
-
-    if (now >= MIDNIGHT && now < MORNING) {
-        drawNight(width, height);
-        alpha(normf(MIDNIGHT, MORNING, now));
-        drawSunrise(width, height);
-    } else if (now >= MORNING && now < AFTERNOON) {
-        drawSunrise(width, height);
-        alpha(normf(MORNING, AFTERNOON, now));
-        drawNoon(width, height);
-    } else if (now >= AFTERNOON && now < DUSK) {
-        drawNoon(width, height);
-        alpha(normf(AFTERNOON, DUSK, now));
-        drawSunset(width, height);
-    } else if (now >= DUSK) {
-        drawNight(width, height);
-        alpha(1.0f - normf(DUSK, 1.0f, now));
-        drawSunset(width, height);
-    }
-
-    drawBlades(now, frameCount);
-
-    frameCount++;
-    storeI32(RSID_STATE, RSID_FRAME_COUNT, frameCount);
-
-    return 1;
-}
diff --git a/libs/rs/java/Grass/src/com/android/grass/rs/Grass.java b/libs/rs/java/Grass/src/com/android/grass/rs/Grass.java
deleted file mode 100644
index 260fcee..0000000
--- a/libs/rs/java/Grass/src/com/android/grass/rs/Grass.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.grass.rs;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-public class Grass extends Activity {
-    private GrassView mView;
-
-    @Override
-    public void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-
-        mView = new GrassView(this);
-        setContentView(mView);
-    }
-
-    @Override
-    protected void onResume() {
-        super.onResume();
-        mView.onResume();
-    }
-
-    @Override
-    protected void onPause() {
-        super.onPause();
-        mView.onPause();
-
-        Runtime.getRuntime().exit(0);
-    }
-}
diff --git a/libs/rs/java/Grass/src/com/android/grass/rs/GrassRS.java b/libs/rs/java/Grass/src/com/android/grass/rs/GrassRS.java
deleted file mode 100644
index 7af600f..0000000
--- a/libs/rs/java/Grass/src/com/android/grass/rs/GrassRS.java
+++ /dev/null
@@ -1,243 +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 com.android.grass.rs;
-
-import android.content.res.Resources;
-import android.renderscript.Sampler;
-import static android.renderscript.ProgramFragment.EnvMode.*;
-import static android.renderscript.ProgramStore.DepthFunc.*;
-import static android.renderscript.ProgramStore.BlendSrcFunc;
-import static android.renderscript.ProgramStore.BlendDstFunc;
-import android.renderscript.RenderScript;
-import android.renderscript.ProgramFragment;
-import android.renderscript.ProgramStore;
-import android.renderscript.Allocation;
-import android.renderscript.ProgramVertex;
-import static android.renderscript.Element.*;
-import static android.util.MathUtils.*;
-import android.renderscript.ScriptC;
-import android.renderscript.Type;
-import android.renderscript.Dimension;
-import static android.renderscript.Sampler.Value.*;
-
-import java.util.TimeZone;
-
-class GrassRS {
-    private static final int RSID_STATE = 0;
-    private static final int RSID_STATE_FRAMECOUNT = 0;
-    private static final int RSID_STATE_BLADES_COUNT = 1;
-    private static final int RSID_STATE_WIDTH = 2;
-    private static final int RSID_STATE_HEIGHT = 3;
-
-    private static final int TEXTURES_COUNT = 5;
-
-    private static final int RSID_BLADES = 1;
-    private static final int BLADES_COUNT = 100;
-    private static final int BLADE_STRUCT_FIELDS_COUNT = 12;
-    private static final int BLADE_STRUCT_ANGLE = 0;
-    private static final int BLADE_STRUCT_SIZE = 1;
-    private static final int BLADE_STRUCT_XPOS = 2;
-    private static final int BLADE_STRUCT_YPOS = 3;
-    private static final int BLADE_STRUCT_OFFSET = 4;
-    private static final int BLADE_STRUCT_SCALE = 5;
-    private static final int BLADE_STRUCT_LENGTHX = 6;
-    private static final int BLADE_STRUCT_LENGTHY = 7;
-    private static final int BLADE_STRUCT_HARDNESS = 8;
-    private static final int BLADE_STRUCT_H = 9;
-    private static final int BLADE_STRUCT_S = 10;
-    private static final int BLADE_STRUCT_B = 11;
-
-    private Resources mResources;
-    private RenderScript mRS;
-
-    private final int mWidth;
-    private final int mHeight;
-
-    private ScriptC mScript;
-    private Sampler mSampler;
-    private ProgramFragment mPfBackground;
-    private ProgramStore mPfsBackground;
-    private ProgramVertex mPvBackground;
-    private ProgramVertex.MatrixAllocation mPvOrthoAlloc;
-
-    private Allocation[] mTextures;
-
-    private Allocation mState;
-    private Allocation mBlades;
-
-    public GrassRS(int width, int height) {
-        mWidth = width;
-        mHeight = height;
-    }
-
-    public void init(RenderScript rs, Resources res) {
-        mRS = rs;
-        mResources = res;
-        initRS();
-    }
-
-    public void destroy() {
-        mScript.destroy();
-        mSampler.destroy();
-        mPfBackground.destroy();
-        mPfsBackground.destroy();
-        mPvBackground.destroy();
-        mPvOrthoAlloc.mAlloc.destroy();
-        for (Allocation a : mTextures) {
-            a.destroy();
-        }
-        mState.destroy();
-        mBlades.destroy();
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            destroy();
-        } finally {
-            super.finalize();
-        }
-    }
-
-    private void initRS() {
-        createProgramVertex();
-        createProgramFragmentStore();
-        createProgramFragment();
-        createScriptStructures();
-        loadTextures();
-
-        ScriptC.Builder sb = new ScriptC.Builder(mRS);
-        sb.setScript(mResources, R.raw.grass);
-        sb.setRoot(true);
-        mScript = sb.create();
-        mScript.setClearColor(0.0f, 0.0f, 0.0f, 1.0f);
-        mScript.setTimeZone(TimeZone.getDefault().getID());
-
-        mScript.bindAllocation(mState, RSID_STATE);
-        mScript.bindAllocation(mBlades, RSID_BLADES);
-
-        mRS.contextBindRootScript(mScript);
-    }
-
-    private void createScriptStructures() {
-        final int[] data = new int[4];
-        mState = Allocation.createSized(mRS, USER_I32, data.length);
-        data[RSID_STATE_FRAMECOUNT] = 0;
-        data[RSID_STATE_BLADES_COUNT] = BLADES_COUNT;
-        data[RSID_STATE_WIDTH] = mWidth;
-        data[RSID_STATE_HEIGHT] = mHeight;
-        mState.data(data);
-
-        final float[] blades = new float[BLADES_COUNT * BLADE_STRUCT_FIELDS_COUNT];
-        mBlades = Allocation.createSized(mRS, USER_FLOAT, blades.length);
-        for (int i = 0; i < blades.length; i+= BLADE_STRUCT_FIELDS_COUNT) {
-            createBlade(blades, i);
-        }
-        mBlades.data(blades);
-    }
-
-    private void createBlade(float[] blades, int index) {
-        //noinspection PointlessArithmeticExpression
-        blades[index + BLADE_STRUCT_ANGLE] = 0.0f;
-        blades[index + BLADE_STRUCT_SIZE] = random(4.0f) + 4.0f;
-        blades[index + BLADE_STRUCT_XPOS] = random(mWidth);
-        blades[index + BLADE_STRUCT_YPOS] = mHeight;
-        blades[index + BLADE_STRUCT_OFFSET] = random(0.2f) - 0.1f;
-        blades[index + BLADE_STRUCT_SCALE] = random(0.6f) + 0.2f;
-        blades[index + BLADE_STRUCT_LENGTHX] = random(4.5f) + 3.0f;
-        blades[index + BLADE_STRUCT_LENGTHY] = random(5.5f) + 2.0f;
-        blades[index + BLADE_STRUCT_HARDNESS] = random(1.0f) + 0.2f;
-        blades[index + BLADE_STRUCT_H] = random(0.02f) + 0.2f;
-        blades[index + BLADE_STRUCT_S] = random(0.22f) + 0.78f;
-        blades[index + BLADE_STRUCT_B] = random(0.65f) + 0.35f;
-    }
-
-    private void loadTextures() {
-        mTextures = new Allocation[TEXTURES_COUNT];
-
-        final Allocation[] textures = mTextures;
-        textures[0] = loadTexture(R.drawable.night, "TNight");
-        textures[1] = loadTexture(R.drawable.sunrise, "TSunrise");
-        textures[2] = loadTexture(R.drawable.sky, "TSky");
-        textures[3] = loadTexture(R.drawable.sunset, "TSunset");
-        textures[4] = generateTextureAlpha(4, 1, new int[] { 0x00FFFF00 }, "TAa");
-
-        final int count = textures.length;
-        for (int i = 0; i < count; i++) {
-            final Allocation texture = textures[i];
-            texture.uploadToTexture(0);
-        }
-    }
-
-    private Allocation generateTextureAlpha(int width, int height, int[] data, String name) {
-        final Type.Builder builder = new Type.Builder(mRS, A_8);
-        builder.add(Dimension.X, width);
-        builder.add(Dimension.Y, height);
-        
-        final Allocation allocation = Allocation.createTyped(mRS, builder.create());
-        allocation.data(data);
-        allocation.setName(name);
-        return allocation;
-    }
-
-    private Allocation loadTexture(int id, String name) {
-        final Allocation allocation = Allocation.createFromBitmapResource(mRS, mResources,
-                id, RGB_565, false);
-        allocation.setName(name);
-        return allocation;
-    }
-
-    private void createProgramFragment() {
-        Sampler.Builder bs = new Sampler.Builder(mRS);
-        bs.setMin(LINEAR);
-        bs.setMag(LINEAR);
-        bs.setWrapS(CLAMP);
-        bs.setWrapT(CLAMP);
-        mSampler = bs.create();
-
-        ProgramFragment.Builder b;
-        b = new ProgramFragment.Builder(mRS, null, null);
-        b.setTexEnable(true, 0);
-        b.setTexEnvMode(REPLACE, 0);
-        mPfBackground = b.create();
-        mPfBackground.setName("PFBackground");
-        mPfBackground.bindSampler(mSampler, 0);
-    }
-
-    private void createProgramFragmentStore() {
-        ProgramStore.Builder b;
-        b = new ProgramStore.Builder(mRS, null, null);
-
-        b.setDepthFunc(ALWAYS);
-        b.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE_MINUS_SRC_ALPHA);
-        b.setDitherEnable(true);
-        b.setDepthMask(false);
-        mPfsBackground = b.create();
-        mPfsBackground.setName("PFSBackground");
-    }
-
-    private void createProgramVertex() {
-        mPvOrthoAlloc = new ProgramVertex.MatrixAllocation(mRS);
-        mPvOrthoAlloc.setupOrthoWindow(mWidth, mHeight);
-
-        ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS, null, null);
-        pvb.setTextureMatrixEnable(true);
-        mPvBackground = pvb.create();
-        mPvBackground.bindAllocation(mPvOrthoAlloc);
-        mPvBackground.setName("PVBackground");
-    }
-}
diff --git a/libs/rs/java/Grass/src/com/android/grass/rs/GrassView.java b/libs/rs/java/Grass/src/com/android/grass/rs/GrassView.java
deleted file mode 100644
index c2b9a66..0000000
--- a/libs/rs/java/Grass/src/com/android/grass/rs/GrassView.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.grass.rs;
-
-import android.content.Context;
-import android.renderscript.RSSurfaceView;
-import android.renderscript.RenderScript;
-import android.view.SurfaceHolder;
-
-class GrassView extends RSSurfaceView {
-    private GrassRS mRender;
-
-    public GrassView(Context context) {
-        super(context);
-    }
-
-    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
-        super.surfaceChanged(holder, format, w, h);
-
-        RenderScript RS = createRenderScript();
-        mRender = new GrassRS(w, h);
-        mRender.init(RS, getResources());
-    }
-
-    @Override
-    public void surfaceDestroyed(SurfaceHolder holder) {
-        if (mRender != null) mRender.destroy();
-    }
-}
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
index 7dbf412..105142b 100644
--- a/libs/rs/rs.spec
+++ b/libs/rs/rs.spec
@@ -44,6 +44,7 @@
 	param RsDataType dataType
 	param bool isNormalized
 	param size_t bits
+	param const char * name
 	}
 
 ElementCreate {
@@ -311,14 +312,18 @@
 	param uint32_t stencil
 	}
 
-ScriptCAddType {
+ScriptSetType {
 	param RsType type
+	param uint32_t slot
+	param const char * name
 	}
 
-ScriptCSetRoot {
+ScriptSetRoot {
 	param bool isRoot
 	}
 
+
+
 ScriptCSetScript {
 	param void * codePtr
 	}
diff --git a/libs/rs/rsComponent.cpp b/libs/rs/rsComponent.cpp
index fde62a0..b88710c 100644
--- a/libs/rs/rsComponent.cpp
+++ b/libs/rs/rsComponent.cpp
@@ -31,12 +31,35 @@
 
 Component::Component(
     DataKind dk, DataType dt,
-    bool isNormalized, uint32_t bits)
+    bool isNormalized, uint32_t bits, const char * name)
 {
     mType = dt;
     mKind = dk;
     mIsNormalized = isNormalized;
     mBits = bits;
+    if (name) {
+        mName = name;
+    }
+}
+
+const char * Component::getCType() const
+{
+    switch(mType) {
+    case FLOAT:
+        return "float";
+    case SIGNED:
+    case UNSIGNED:
+        switch(mBits) {
+        case 32:
+            return "int";
+        case 16:
+            return "short";
+        case 8:
+            return "char";
+        }
+        break;
+    }
+    return NULL;
 }
 
 Component::~Component()
diff --git a/libs/rs/rsComponent.h b/libs/rs/rsComponent.h
index 9db107f..6342f1b 100644
--- a/libs/rs/rsComponent.h
+++ b/libs/rs/rsComponent.h
@@ -44,7 +44,7 @@
     };
 
 
-    Component(DataKind dk, DataType dt, bool isNormalized, uint32_t bits);
+    Component(DataKind dk, DataType dt, bool isNorm, uint32_t bits, const char *);
     virtual ~Component();
 
     DataType getType() const {return mType;}
@@ -53,6 +53,9 @@
     uint32_t getBits() const {return mBits;}
 
     uint32_t getGLType() const;
+    const char * getCType() const;
+
+    const char * getComponentName() const {return mName.string();}
 
 protected:
 
@@ -60,6 +63,7 @@
     bool mIsNormalized;
     DataKind mKind;
     uint32_t mBits;
+    String8 mName;
 
 private:
     Component();
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 9de23b3..2860452 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -17,7 +17,6 @@
 #include "rsDevice.h"
 #include "rsContext.h"
 #include "rsThreadIO.h"
-#include "utils/String8.h"
 #include <ui/FramebufferNativeWindow.h>
 
 #include <GLES/gl.h>
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index 54c555f..60a526b 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -19,9 +19,6 @@
 
 #include "rsUtils.h"
 
-#include <utils/KeyedVector.h>
-#include <utils/String8.h>
-#include <utils/Vector.h>
 #include <ui/Surface.h>
 
 #include "rsType.h"
diff --git a/libs/rs/rsElement.cpp b/libs/rs/rsElement.cpp
index 0c5cb18..97b18c0 100644
--- a/libs/rs/rsElement.cpp
+++ b/libs/rs/rsElement.cpp
@@ -23,45 +23,45 @@
 
 void ElementState::initPredefined()
 {
-    Component * u_8  = new Component(Component::USER,   Component::UNSIGNED,  true,  8);
-    Component * i_8  = new Component(Component::USER,   Component::SIGNED,    true,  8);
-    Component * u_16 = new Component(Component::USER,   Component::UNSIGNED,  true,  16);
-    Component * i_16 = new Component(Component::USER,   Component::SIGNED,    true,  16);
-    Component * u_32 = new Component(Component::USER,   Component::UNSIGNED,  true,  32);
-    Component * i_32 = new Component(Component::USER,   Component::SIGNED,    true,  32);
-    Component * f_32 = new Component(Component::USER,   Component::FLOAT,     true,  32);
+    Component * u_8  = new Component(Component::USER,   Component::UNSIGNED,  true,  8, 0);
+    Component * i_8  = new Component(Component::USER,   Component::SIGNED,    true,  8, 0);
+    Component * u_16 = new Component(Component::USER,   Component::UNSIGNED,  true,  16, 0);
+    Component * i_16 = new Component(Component::USER,   Component::SIGNED,    true,  16, 0);
+    Component * u_32 = new Component(Component::USER,   Component::UNSIGNED,  true,  32, 0);
+    Component * i_32 = new Component(Component::USER,   Component::SIGNED,    true,  32, 0);
+    Component * f_32 = new Component(Component::USER,   Component::FLOAT,     true,  32, 0);
 
 
-    Component * r_4  = new Component(Component::RED,    Component::UNSIGNED,  true,  4);
-    Component * r_5  = new Component(Component::RED,    Component::UNSIGNED,  true,  5);
-    Component * r_8  = new Component(Component::RED,    Component::UNSIGNED,  true,  8);
+    Component * r_4  = new Component(Component::RED,    Component::UNSIGNED,  true,  4, 0);
+    Component * r_5  = new Component(Component::RED,    Component::UNSIGNED,  true,  5, 0);
+    Component * r_8  = new Component(Component::RED,    Component::UNSIGNED,  true,  8, 0);
 
-    Component * g_4  = new Component(Component::GREEN,  Component::UNSIGNED,  true,  4);
-    Component * g_5  = new Component(Component::GREEN,  Component::UNSIGNED,  true,  5);
-    Component * g_6  = new Component(Component::GREEN,  Component::UNSIGNED,  true,  6);
-    Component * g_8  = new Component(Component::GREEN,  Component::UNSIGNED,  true,  8);
+    Component * g_4  = new Component(Component::GREEN,  Component::UNSIGNED,  true,  4, 0);
+    Component * g_5  = new Component(Component::GREEN,  Component::UNSIGNED,  true,  5, 0);
+    Component * g_6  = new Component(Component::GREEN,  Component::UNSIGNED,  true,  6, 0);
+    Component * g_8  = new Component(Component::GREEN,  Component::UNSIGNED,  true,  8, 0);
 
-    Component * b_4  = new Component(Component::BLUE,   Component::UNSIGNED,  true,  4);
-    Component * b_5  = new Component(Component::BLUE,   Component::UNSIGNED,  true,  5);
-    Component * b_8  = new Component(Component::BLUE,   Component::UNSIGNED,  true,  8);
+    Component * b_4  = new Component(Component::BLUE,   Component::UNSIGNED,  true,  4, 0);
+    Component * b_5  = new Component(Component::BLUE,   Component::UNSIGNED,  true,  5, 0);
+    Component * b_8  = new Component(Component::BLUE,   Component::UNSIGNED,  true,  8, 0);
 
-    Component * a_1  = new Component(Component::ALPHA,  Component::UNSIGNED,  true,  1);
-    Component * a_4  = new Component(Component::ALPHA,  Component::UNSIGNED,  true,  4);
-    Component * a_8  = new Component(Component::ALPHA,  Component::UNSIGNED,  true,  8);
+    Component * a_1  = new Component(Component::ALPHA,  Component::UNSIGNED,  true,  1, 0);
+    Component * a_4  = new Component(Component::ALPHA,  Component::UNSIGNED,  true,  4, 0);
+    Component * a_8  = new Component(Component::ALPHA,  Component::UNSIGNED,  true,  8, 0);
 
-    Component * idx_16 = new Component(Component::INDEX,  Component::UNSIGNED,  false, 16);
-    Component * idx_32 = new Component(Component::INDEX,  Component::UNSIGNED,  false, 32);
+    Component * idx_16 = new Component(Component::INDEX,  Component::UNSIGNED,  false, 16, 0);
+    Component * idx_32 = new Component(Component::INDEX,  Component::UNSIGNED,  false, 32, 0);
 
-    Component * x    = new Component(Component::X,      Component::FLOAT,     false, 32);
-    Component * y    = new Component(Component::Y,      Component::FLOAT,     false, 32);
-    Component * z    = new Component(Component::Z,      Component::FLOAT,     false, 32);
+    Component * x    = new Component(Component::X,      Component::FLOAT,     false, 32, 0);
+    Component * y    = new Component(Component::Y,      Component::FLOAT,     false, 32, 0);
+    Component * z    = new Component(Component::Z,      Component::FLOAT,     false, 32, 0);
 
-    Component * nx   = new Component(Component::NX,     Component::FLOAT,     false, 32);
-    Component * ny   = new Component(Component::NY,     Component::FLOAT,     false, 32);
-    Component * nz   = new Component(Component::NZ,     Component::FLOAT,     false, 32);
+    Component * nx   = new Component(Component::NX,     Component::FLOAT,     false, 32, 0);
+    Component * ny   = new Component(Component::NY,     Component::FLOAT,     false, 32, 0);
+    Component * nz   = new Component(Component::NZ,     Component::FLOAT,     false, 32, 0);
 
-    Component * s    = new Component(Component::S,      Component::FLOAT,     false, 32);
-    Component * t    = new Component(Component::T,      Component::FLOAT,     false, 32);
+    Component * s    = new Component(Component::S,      Component::FLOAT,     false, 32, 0);
+    Component * t    = new Component(Component::T,      Component::FLOAT,     false, 32, 0);
 
     Element * e;
 
@@ -391,14 +391,14 @@
     return e;
 }
 
-void rsi_ElementAdd(Context *rsc, RsDataKind dk, RsDataType dt, bool isNormalized, size_t bits)
+void rsi_ElementAdd(Context *rsc, RsDataKind dk, RsDataType dt, bool isNormalized, size_t bits, const char *name)
 {
     ElementState * sec = &rsc->mStateElement;
-
     Component *c = new Component(static_cast<Component::DataKind>(dk),
                                  static_cast<Component::DataType>(dt),
                                  isNormalized,
-                                 bits);
+                                 bits,
+                                 name);
     sec->mComponentBuildList.add(c);
 }
 
diff --git a/libs/rs/rsFileA3D.cpp b/libs/rs/rsFileA3D.cpp
index 86d294b..347ef23 100644
--- a/libs/rs/rsFileA3D.cpp
+++ b/libs/rs/rsFileA3D.cpp
@@ -334,7 +334,7 @@
         uint32_t bits = io->loadU8();
         bool isNorm = io->loadU8() != 0;
         LOGE("  %i %i %i %i", dk, dt, bits, isNorm);
-        rsi_ElementAdd(rsc, dk, dt, isNorm, bits);
+        rsi_ElementAdd(rsc, dk, dt, isNorm, bits, 0);
     }
     LOGE("processChunk_Element create");
     ie->mRsObj = rsi_ElementCreate(rsc);
diff --git a/libs/rs/rsScript.cpp b/libs/rs/rsScript.cpp
index 6ce9f61..75c994b 100644
--- a/libs/rs/rsScript.cpp
+++ b/libs/rs/rsScript.cpp
@@ -76,6 +76,25 @@
     s->mEnviroment.mClearStencil = v;
 }
 
+void rsi_ScriptSetType(Context * rsc, RsType vt, uint32_t slot, const char *name)
+{
+    ScriptCState *ss = &rsc->mScriptC;
+    const Type *t = static_cast<const Type *>(vt);
+    ss->mConstantBufferTypes[slot].set(t);
+    if (name) {
+        ss->mSlotNames[slot].setTo(name);
+    } else {
+        ss->mSlotNames[slot].setTo("");
+    }
+}
+
+void rsi_ScriptSetRoot(Context * rsc, bool isRoot)
+{
+    ScriptCState *ss = &rsc->mScriptC;
+    ss->mEnviroment.mIsRoot = isRoot;
+}
+
+
 }
 }
 
diff --git a/libs/rs/rsScript.h b/libs/rs/rsScript.h
index a8e04a6..dc66763 100644
--- a/libs/rs/rsScript.h
+++ b/libs/rs/rsScript.h
@@ -29,6 +29,8 @@
 class ProgramRaster;
 class ProgramFragmentStore;
 
+#define MAX_SCRIPT_BANKS 16
+
 class Script : public ObjectBase
 {
 public:
@@ -54,10 +56,11 @@
     };
     Enviroment_t mEnviroment;
 
-    const Type * mConstantBufferTypes;
     uint32_t mCounstantBufferCount;
 
-    ObjectBaseRef<Allocation> mSlots[16];
+    ObjectBaseRef<Allocation> mSlots[MAX_SCRIPT_BANKS];
+    ObjectBaseRef<const Type> mTypes[MAX_SCRIPT_BANKS];
+    String8 mSlotNames[MAX_SCRIPT_BANKS];
 
     virtual bool run(Context *, uint32_t launchID) = 0;
 };
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index 3343db5..ced2516 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -19,7 +19,6 @@
 #include "rsMatrix.h"
 
 #include "acc/acc.h"
-#include "utils/String8.h"
 #include "utils/Timers.h"
 
 #include <GLES/gl.h>
@@ -91,7 +90,10 @@
 {
     memset(&mProgram, 0, sizeof(mProgram));
 
-    mConstantBufferTypes.clear();
+    for (uint32_t ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
+        mConstantBufferTypes[ct].clear();
+        mSlotNames[ct].setTo("");
+    }
 
     memset(&mEnviroment, 0, sizeof(mEnviroment));
     mEnviroment.mClearColor[0] = 0;
@@ -127,6 +129,7 @@
     appendDecls(&tmp);
     rsc->appendVarDefines(&tmp);
     appendVarDefines(&tmp);
+    appendTypes(&tmp);
     tmp.append("#line 1\n");
 
     const char* scriptSource[] = {tmp.string(), mProgram.mScriptText};
@@ -242,6 +245,63 @@
     }
 }
 
+void ScriptCState::appendTypes(String8 *str)
+{
+    char buf[256];
+    String8 tmp;
+
+    for (size_t ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
+        const Type *t = mConstantBufferTypes[ct].get();
+        if (!t) {
+            continue;
+        }
+        const Element *e = t->getElement();
+
+        if (t->getName()) {
+            for (size_t ct2=0; ct2 < e->getComponentCount(); ct2++) {
+                const Component *c = e->getComponent(ct2);
+                tmp.setTo("#define OFFSETOF_");
+                tmp.append(t->getName());
+                tmp.append("_");
+                tmp.append(c->getComponentName());
+                sprintf(buf, " %i\n", ct2);
+                tmp.append(buf);
+                LOGD(tmp);
+                str->append(tmp);
+            }
+        }
+
+        if (mSlotNames[ct].length() > 0) {
+            for (size_t ct2=0; ct2 < e->getComponentCount(); ct2++) {
+                const Component *c = e->getComponent(ct2);
+                tmp.setTo("#define ");
+                tmp.append(mSlotNames[ct]);
+                tmp.append("_");
+                tmp.append(c->getComponentName());
+                switch (c->getType()) {
+                case Component::FLOAT:
+                    tmp.append(" loadF(");
+                    break;
+                case Component::SIGNED:
+                    sprintf(buf, " loadI%i(", c->getBits());
+                    tmp.append(buf);
+                    break;
+                case Component::UNSIGNED:
+                    sprintf(buf, " loadU%i(", c->getBits());
+                    tmp.append(buf);
+                    break;
+                }
+                sprintf(buf, "%i, %i)\n", ct, ct2);
+                tmp.append(buf);
+
+                LOGD(tmp);
+                str->append(tmp);
+            }
+        }
+    }
+
+}
+
 
 namespace android {
 namespace renderscript {
@@ -252,24 +312,12 @@
     ss->clear();
 }
 
-void rsi_ScriptCAddType(Context * rsc, RsType vt)
-{
-    ScriptCState *ss = &rsc->mScriptC;
-    ss->mConstantBufferTypes.add(static_cast<const Type *>(vt));
-}
-
 void rsi_ScriptCSetScript(Context * rsc, void *vp)
 {
     ScriptCState *ss = &rsc->mScriptC;
     ss->mProgram.mScript = reinterpret_cast<ScriptC::RunScript_t>(vp);
 }
 
-void rsi_ScriptCSetRoot(Context * rsc, bool isRoot)
-{
-    ScriptCState *ss = &rsc->mScriptC;
-    ss->mEnviroment.mIsRoot = isRoot;
-}
-
 void rsi_ScriptCSetText(Context *rsc, const char *text, uint32_t len)
 {
     ScriptCState *ss = &rsc->mScriptC;
@@ -290,8 +338,12 @@
     ss->mAccScript = NULL;
     s->mEnviroment = ss->mEnviroment;
     s->mProgram = ss->mProgram;
-    ss->clear();
+    for (int ct=0; ct < MAX_SCRIPT_BANKS; ct++) {
+        s->mTypes[ct].set(ss->mConstantBufferTypes[ct].get());
+        s->mSlotNames[ct] = ss->mSlotNames[ct];
+    }
 
+    ss->clear();
     return s;
 }
 
diff --git a/libs/rs/rsScriptC.h b/libs/rs/rsScriptC.h
index ad0e3ee..32a9079 100644
--- a/libs/rs/rsScriptC.h
+++ b/libs/rs/rsScriptC.h
@@ -68,11 +68,13 @@
     ScriptC::Program_t mProgram;
     Script::Enviroment_t mEnviroment;
 
-    Vector<const Type *> mConstantBufferTypes;
+    ObjectBaseRef<const Type> mConstantBufferTypes[MAX_SCRIPT_BANKS];
+    String8 mSlotNames[MAX_SCRIPT_BANKS];
 
     void clear();
     void runCompiler(Context *rsc);
     void appendVarDefines(String8 *str);
+    void appendTypes(String8 *str);
 
     struct SymbolTable_t {
         const char * mName;
diff --git a/libs/rs/rsScriptC_Lib.cpp b/libs/rs/rsScriptC_Lib.cpp
index 4ee112d..c13894b 100644
--- a/libs/rs/rsScriptC_Lib.cpp
+++ b/libs/rs/rsScriptC_Lib.cpp
@@ -20,7 +20,6 @@
 #include "rsNoise.h"
 
 #include "acc/acc.h"
-#include "utils/String8.h"
 #include "utils/Timers.h"
 
 #include <GLES/gl.h>
diff --git a/libs/rs/rsUtils.h b/libs/rs/rsUtils.h
index f0e4750..ec928db 100644
--- a/libs/rs/rsUtils.h
+++ b/libs/rs/rsUtils.h
@@ -21,6 +21,8 @@
 #define LOG_TAG "rs"
 #include <utils/Log.h>
 #include <utils/Vector.h>
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
 #include <stdlib.h>
 #include <pthread.h>
 #include <time.h>
diff --git a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index a479b4c..3f607f6 100644
--- a/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/libs/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -166,9 +166,17 @@
         }
     }
 
+    eglQuerySurface(display, surface, EGL_WIDTH,  &mWidth);
+    eglQuerySurface(display, surface, EGL_HEIGHT, &mHeight);
+
 #ifdef EGL_ANDROID_swap_rectangle    
     if (strstr(egl_extensions, "EGL_ANDROID_swap_rectangle")) {
-        mFlags |= SWAP_RECTANGLE;
+        if (eglSetSwapRectangleANDROID(display, surface,
+                0, 0, mWidth, mHeight) == EGL_TRUE) {
+            // This could fail if this extension is not supported by this
+            // specific surface (of config)
+            mFlags |= SWAP_RECTANGLE;
+        }
     }
     // when we have the choice between UPDATE_ON_DEMAND and SWAP_RECTANGLE
     // choose UPDATE_ON_DEMAND, which is more efficient
@@ -177,13 +185,15 @@
 #endif
     
 
+    LOGI("flags     : %08x", mFlags);
+    
     mDpiX = mNativeWindow->xdpi;
     mDpiY = mNativeWindow->ydpi;
     mRefreshRate = fbDev->fps; 
     
     char property[PROPERTY_VALUE_MAX];
     /* Read density from build-specific ro.sf.lcd_density property
-     * except if it is overriden by qemu.sf.lcd_density.
+     * except if it is overridden by qemu.sf.lcd_density.
      */
     if (property_get("qemu.sf.lcd_density", property, NULL) <= 0) {
         if (property_get("ro.sf.lcd_density", property, NULL) <= 0) {
@@ -204,9 +214,6 @@
     context = eglCreateContext(display, config, NULL, NULL);
     //checkEGLErrors("eglCreateContext");
     
-    eglQuerySurface(display, surface, EGL_WIDTH, &mWidth);
-    eglQuerySurface(display, surface, EGL_HEIGHT, &mHeight);
-    
     
     /*
      * Gather OpenGL ES extensions
diff --git a/libs/surfaceflinger/Layer.cpp b/libs/surfaceflinger/Layer.cpp
index d1142cc..8c0b40d 100644
--- a/libs/surfaceflinger/Layer.cpp
+++ b/libs/surfaceflinger/Layer.cpp
@@ -217,7 +217,7 @@
     drawWithOpenGL(clip, mTextures[index]);
 }
 
-sp<SurfaceBuffer> Layer::peekBuffer()
+sp<SurfaceBuffer> Layer::peekBuffer(int usage)
 {
     /*
      * This is called from the client's Surface::lock(), after it locked
@@ -250,7 +250,7 @@
     }
     
     LayerBitmap& layerBitmap(mBuffers[backBufferIndex]);
-    sp<SurfaceBuffer> buffer = layerBitmap.allocate();
+    sp<SurfaceBuffer> buffer = layerBitmap.allocate(usage);
     
     LOGD_IF(DEBUG_RESIZE,
             "Layer::getBuffer(this=%p), index=%d, (%d,%d), (%d,%d)",
@@ -649,12 +649,12 @@
 {
 }
 
-sp<SurfaceBuffer> Layer::SurfaceLayer::getBuffer()
+sp<SurfaceBuffer> Layer::SurfaceLayer::getBuffer(int usage)
 {
     sp<SurfaceBuffer> buffer = 0;
     sp<Layer> owner(getOwner());
     if (owner != 0) {
-        buffer = owner->peekBuffer();
+        buffer = owner->peekBuffer(usage);
     }
     return buffer;
 }
diff --git a/libs/surfaceflinger/Layer.h b/libs/surfaceflinger/Layer.h
index 4c13d6e..add5d50 100644
--- a/libs/surfaceflinger/Layer.h
+++ b/libs/surfaceflinger/Layer.h
@@ -101,7 +101,7 @@
 
     status_t resize(int32_t index, uint32_t w, uint32_t h, const char* what);
     Region post(uint32_t* oldState, bool& recomputeVisibleRegions);
-    sp<SurfaceBuffer> peekBuffer();
+    sp<SurfaceBuffer> peekBuffer(int usage);
     void destroy();
     void scheduleBroadcast();
 
@@ -114,7 +114,7 @@
                 ~SurfaceLayer();
 
     private:
-        virtual sp<SurfaceBuffer> getBuffer();
+        virtual sp<SurfaceBuffer> getBuffer(int usage);
 
         sp<Layer> getOwner() const {
             return static_cast<Layer*>(Surface::getOwner().get());
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
index fbce73d..419574c 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/libs/surfaceflinger/LayerBase.cpp
@@ -759,7 +759,7 @@
     return BnSurface::onTransact(code, data, reply, flags);
 }
 
-sp<SurfaceBuffer> LayerBaseClient::Surface::getBuffer() 
+sp<SurfaceBuffer> LayerBaseClient::Surface::getBuffer(int) 
 {
     return NULL; 
 }
diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h
index 6fb1d1c..65bf55b 100644
--- a/libs/surfaceflinger/LayerBase.h
+++ b/libs/surfaceflinger/LayerBase.h
@@ -335,7 +335,7 @@
         sp<LayerBaseClient> getOwner() const;
 
     private:
-        virtual sp<SurfaceBuffer> getBuffer();
+        virtual sp<SurfaceBuffer> getBuffer(int usage);
         virtual status_t registerBuffers(const ISurface::BufferHeap& buffers); 
         virtual void postBuffer(ssize_t offset);
         virtual void unregisterBuffers();
diff --git a/libs/surfaceflinger/LayerBitmap.cpp b/libs/surfaceflinger/LayerBitmap.cpp
index 5221fed..5e74451 100644
--- a/libs/surfaceflinger/LayerBitmap.cpp
+++ b/libs/surfaceflinger/LayerBitmap.cpp
@@ -38,13 +38,14 @@
 // Buffer and implementation of android_native_buffer_t
 // ===========================================================================
 
-Buffer::Buffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags)
+Buffer::Buffer(uint32_t w, uint32_t h, PixelFormat format,
+        uint32_t reqUsage, uint32_t flags)
     : SurfaceBuffer(), mInitCheck(NO_INIT), mFlags(flags), 
     mVStride(0)
 {
     this->format = format;
     if (w>0 && h>0) {
-        mInitCheck = initSize(w, h);
+        mInitCheck = initSize(w, h, reqUsage);
     }
 }
 
@@ -65,7 +66,7 @@
     return static_cast<android_native_buffer_t*>(const_cast<Buffer*>(this));
 }
 
-status_t Buffer::initSize(uint32_t w, uint32_t h)
+status_t Buffer::initSize(uint32_t w, uint32_t h, uint32_t reqUsage)
 {
     status_t err = NO_ERROR;
 
@@ -88,16 +89,9 @@
         usage = BufferAllocator::USAGE_SW_READ_OFTEN | 
                 BufferAllocator::USAGE_SW_WRITE_OFTEN;
     } else {
-        if (mFlags & Buffer::GPU) {
-            // the client wants to do GL rendering
-            usage = BufferAllocator::USAGE_HW_RENDER |
-                    BufferAllocator::USAGE_HW_TEXTURE;
-        } else {
-            // software rendering-client, h/w composition
-            usage = BufferAllocator::USAGE_SW_READ_OFTEN | 
-                    BufferAllocator::USAGE_SW_WRITE_OFTEN |
-                    BufferAllocator::USAGE_HW_TEXTURE;
-        }
+        // it's allowed to modify the usage flags here, but generally
+        // the requested flags should be honored.
+        usage = reqUsage | BufferAllocator::USAGE_HW_TEXTURE;
     }
 
     err = allocator.alloc(w, h, format, usage, &handle, &stride);
@@ -174,12 +168,12 @@
     return NO_ERROR;
 }
 
-sp<Buffer> LayerBitmap::allocate()
+sp<Buffer> LayerBitmap::allocate(uint32_t reqUsage)
 {
     Mutex::Autolock _l(mLock);
     surface_info_t* info = mInfo;
     mBuffer.clear(); // free buffer before allocating a new one
-    sp<Buffer> buffer = new Buffer(mWidth, mHeight, mFormat, mFlags);
+    sp<Buffer> buffer = new Buffer(mWidth, mHeight, mFormat, reqUsage, mFlags);
     status_t err = buffer->initCheck();
     if (LIKELY(err == NO_ERROR)) {
         info->flags  = surface_info_t::eBufferDirty;
diff --git a/libs/surfaceflinger/LayerBitmap.h b/libs/surfaceflinger/LayerBitmap.h
index 22525ce..48ee553 100644
--- a/libs/surfaceflinger/LayerBitmap.h
+++ b/libs/surfaceflinger/LayerBitmap.h
@@ -58,7 +58,8 @@
     };
 
     // creates w * h buffer
-    Buffer(uint32_t w, uint32_t h, PixelFormat format, uint32_t flags = 0);
+    Buffer(uint32_t w, uint32_t h, PixelFormat format,
+            uint32_t reqUsage, uint32_t flags = 0);
 
     // return status
     status_t initCheck() const;
@@ -81,7 +82,7 @@
     Buffer& operator = (const Buffer& rhs);
     const Buffer& operator = (const Buffer& rhs) const;
 
-    status_t initSize(uint32_t w, uint32_t h);
+    status_t initSize(uint32_t w, uint32_t h, uint32_t reqUsage);
 
     ssize_t                 mInitCheck;
     uint32_t                mFlags;
@@ -108,7 +109,7 @@
 
     status_t setSize(uint32_t w, uint32_t h);
 
-    sp<Buffer> allocate();
+    sp<Buffer> allocate(uint32_t reqUsage);
     status_t free();
     
     sp<const Buffer>  getBuffer() const { return mBuffer; }
diff --git a/libs/surfaceflinger/LayerBuffer.cpp b/libs/surfaceflinger/LayerBuffer.cpp
index 90e7f50..bd6d472f 100644
--- a/libs/surfaceflinger/LayerBuffer.cpp
+++ b/libs/surfaceflinger/LayerBuffer.cpp
@@ -28,6 +28,7 @@
 
 #include <hardware/copybit.h>
 
+#include "BufferAllocator.h"
 #include "LayerBuffer.h"
 #include "SurfaceFlinger.h"
 #include "DisplayHardware/DisplayHardware.h"
@@ -464,7 +465,9 @@
                         mTempBitmap->getWidth() < tmp_w || 
                         mTempBitmap->getHeight() < tmp_h) {
                     mTempBitmap.clear();
-                    mTempBitmap = new android::Buffer(tmp_w, tmp_h, src.img.format);
+                    mTempBitmap = new android::Buffer(
+                            tmp_w, tmp_h, src.img.format,
+                            BufferAllocator::USAGE_HW_2D);
                     err = mTempBitmap->initCheck();
                 }
 
diff --git a/libs/surfaceflinger/LayerDim.cpp b/libs/surfaceflinger/LayerDim.cpp
index 8e9df9c..f613767 100644
--- a/libs/surfaceflinger/LayerDim.cpp
+++ b/libs/surfaceflinger/LayerDim.cpp
@@ -21,6 +21,7 @@
 #include <utils/Errors.h>
 #include <utils/Log.h>
 
+#include "BufferAllocator.h"
 #include "LayerDim.h"
 #include "SurfaceFlinger.h"
 #include "DisplayHardware/DisplayHardware.h"
@@ -68,7 +69,10 @@
 
     if (LIKELY(flags & DisplayHardware::DIRECT_TEXTURE)) {
         // TODO: api to pass the usage flags
-        sp<Buffer> buffer = new Buffer(w, h, PIXEL_FORMAT_RGB_565);
+        sp<Buffer> buffer = new Buffer(w, h, PIXEL_FORMAT_RGB_565,
+                 BufferAllocator::USAGE_SW_WRITE_OFTEN |
+                 BufferAllocator::USAGE_HW_TEXTURE);
+        
         android_native_buffer_t* clientBuf = buffer->getNativeBuffer();
 
         glGenTextures(1, &sTexId);
@@ -92,7 +96,7 @@
 
         // initialize the texture with zeros
         GGLSurface t;
-        buffer->lock(&t, GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN);
+        buffer->lock(&t, GRALLOC_USAGE_SW_WRITE_OFTEN);
         memset(t.data, 0, t.stride * t.height * 2);
         buffer->unlock();
         sUseTexture = true;
diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp
index f6c666d..90b5163 100644
--- a/libs/ui/FramebufferNativeWindow.cpp
+++ b/libs/ui/FramebufferNativeWindow.cpp
@@ -132,6 +132,7 @@
     android_native_window_t::lockBuffer = lockBuffer;
     android_native_window_t::queueBuffer = queueBuffer;
     android_native_window_t::query = query;
+    android_native_window_t::perform = perform;
 }
 
 FramebufferNativeWindow::~FramebufferNativeWindow() 
@@ -235,6 +236,18 @@
     return BAD_VALUE;
 }
 
+int FramebufferNativeWindow::perform(android_native_window_t* window,
+        int operation, ...)
+{
+    switch (operation) {
+        case NATIVE_WINDOW_SET_USAGE:
+            break;
+        default:
+            return NAME_NOT_FOUND;
+    }
+    return NO_ERROR;
+}
+
 // ----------------------------------------------------------------------------
 }; // namespace android
 // ----------------------------------------------------------------------------
diff --git a/libs/ui/ISurface.cpp b/libs/ui/ISurface.cpp
index 9fbae1e..b78e8b5 100644
--- a/libs/ui/ISurface.cpp
+++ b/libs/ui/ISurface.cpp
@@ -71,10 +71,11 @@
     {
     }
 
-    virtual sp<SurfaceBuffer> getBuffer()
+    virtual sp<SurfaceBuffer> getBuffer(int usage)
     {
         Parcel data, reply;
         data.writeInterfaceToken(ISurface::getInterfaceDescriptor());
+        data.writeInt32(usage);
         remote()->transact(GET_BUFFER, data, &reply);
         sp<SurfaceBuffer> buffer = new SurfaceBuffer(reply);
         return buffer;
@@ -135,7 +136,8 @@
     switch(code) {
         case GET_BUFFER: {
             CHECK_INTERFACE(ISurface, data, reply);
-            sp<SurfaceBuffer> buffer(getBuffer());
+            int usage = data.readInt32();
+            sp<SurfaceBuffer> buffer(getBuffer(usage));
             return SurfaceBuffer::writeToParcel(reply, buffer.get());
         }
         case REGISTER_BUFFERS: {
diff --git a/libs/ui/Surface.cpp b/libs/ui/Surface.cpp
index 4abb7f6..2b6905f 100644
--- a/libs/ui/Surface.cpp
+++ b/libs/ui/Surface.cpp
@@ -414,6 +414,7 @@
     android_native_window_t::lockBuffer       = lockBuffer;
     android_native_window_t::queueBuffer      = queueBuffer;
     android_native_window_t::query            = query;
+    android_native_window_t::perform          = perform;
     mSwapRectangle.makeInvalid();
     DisplayInfo dinfo;
     SurfaceComposerClient::getDisplayInfo(0, &dinfo);
@@ -423,6 +424,8 @@
     const_cast<int&>(android_native_window_t::minSwapInterval) = 1;
     const_cast<int&>(android_native_window_t::maxSwapInterval) = 1;
     const_cast<uint32_t&>(android_native_window_t::flags) = 0;
+    // be default we request a hardware surface
+    mUsage = GRALLOC_USAGE_HW_RENDER;
 }
 
 
@@ -512,6 +515,17 @@
     return self->query(what, value);
 }
 
+int Surface::perform(android_native_window_t* window, 
+        int operation, ...)
+{
+    va_list args;
+    va_start(args, operation);
+    Surface* self = getSelf(window);
+    int res = self->perform(operation, args);
+    va_end(args);
+    return res;
+}
+
 // ----------------------------------------------------------------------------
 
 status_t Surface::dequeueBuffer(sp<SurfaceBuffer>* buffer)
@@ -561,7 +575,7 @@
 
     volatile const surface_info_t* const back = lcblk->surface + backIdx;
     if (back->flags & surface_info_t::eNeedNewBuffer) {
-        err = getBufferLocked(backIdx);
+        err = getBufferLocked(backIdx, mUsage);
     }
 
     if (err == NO_ERROR) {
@@ -627,6 +641,20 @@
     return BAD_VALUE;
 }
 
+int Surface::perform(int operation, va_list args)
+{
+    int res = NO_ERROR;
+    switch (operation) {
+        case NATIVE_WINDOW_SET_USAGE:
+            mUsage = va_arg(args, int);
+            break;
+        default:
+            res = NAME_NOT_FOUND;
+            break;
+    }
+    return res;
+}
+
 // ----------------------------------------------------------------------------
 
 status_t Surface::lock(SurfaceInfo* info, bool blocking) {
@@ -636,6 +664,9 @@
 status_t Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking) 
 {
     // FIXME: needs some locking here
+
+    // we're intending to do software rendering from this point
+    mUsage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN;
     
     sp<SurfaceBuffer> backBuffer;
     status_t err = dequeueBuffer(&backBuffer);
@@ -725,10 +756,10 @@
     mSwapRectangle = r;
 }
 
-status_t Surface::getBufferLocked(int index)
+status_t Surface::getBufferLocked(int index, int usage)
 {
     status_t err = NO_MEMORY;
-    sp<SurfaceBuffer> buffer = mSurface->getBuffer();
+    sp<SurfaceBuffer> buffer = mSurface->getBuffer(usage);
     LOGE_IF(buffer==0, "ISurface::getBuffer() returned NULL");
     if (buffer != 0) {
         sp<SurfaceBuffer>& currentBuffer(mBuffers[index]);
diff --git a/libs/utils/Asset.cpp b/libs/utils/Asset.cpp
index 23cb72d..4295123 100644
--- a/libs/utils/Asset.cpp
+++ b/libs/utils/Asset.cpp
@@ -27,6 +27,7 @@
 #include <utils/ZipUtils.h>
 #include <utils/ZipFileRO.h>
 #include <utils/Log.h>
+#include <utils/threads.h>
 
 #include <string.h>
 #include <memory.h>
@@ -40,24 +41,71 @@
 # define O_BINARY 0
 #endif
 
-static volatile int32_t gCount = 0;
+static Mutex gAssetLock;
+static int32_t gCount = 0;
+static Asset* gHead = NULL;
+static Asset* gTail = NULL;
 
 int32_t Asset::getGlobalCount()
 {
+    AutoMutex _l(gAssetLock);
     return gCount;
 }
 
+String8 Asset::getAssetAllocations()
+{
+    AutoMutex _l(gAssetLock);
+    String8 res;
+    Asset* cur = gHead;
+    while (cur != NULL) {
+        if (cur->isAllocated()) {
+            res.append("    ");
+            res.append(cur->getAssetSource());
+            off_t size = (cur->getLength()+512)/1024;
+            char buf[64];
+            sprintf(buf, ": %dK\n", (int)size);
+            res.append(buf);
+        }
+        cur = cur->mNext;
+    }
+    
+    return res;
+}
+
 Asset::Asset(void)
     : mAccessMode(ACCESS_UNKNOWN)
 {
-    int count = android_atomic_inc(&gCount)+1;
-    //LOGI("Creating Asset %p #%d\n", this, count);
+    AutoMutex _l(gAssetLock);
+    gCount++;
+    mNext = mPrev = NULL;
+    if (gTail == NULL) {
+        gHead = gTail = this;
+  	} else {
+  	    mPrev = gTail;
+  	    gTail->mNext = this;
+  	    gTail = this;
+  	}
+    //LOGI("Creating Asset %p #%d\n", this, gCount);
 }
 
 Asset::~Asset(void)
 {
-    int count = android_atomic_dec(&gCount);
-    //LOGI("Destroying Asset in %p #%d\n", this, count);
+    AutoMutex _l(gAssetLock);
+	gCount--;
+    if (gHead == this) {
+        gHead = mNext;
+    }
+    if (gTail == this) {
+        gTail = mPrev;
+    }
+    if (mNext != NULL) {
+        mNext->mPrev = mPrev;
+    }
+    if (mPrev != NULL) {
+        mPrev->mNext = mNext;
+    }
+    mNext = mPrev = NULL;
+    //LOGI("Destroying Asset in %p #%d\n", this, gCount);
 }
 
 /*
diff --git a/media/libdrm/mobile2/src/util/domcore/NodeIterator.cpp b/media/libdrm/mobile2/src/util/domcore/NodeIterator.cpp
index f076cda..fe13669 100644
--- a/media/libdrm/mobile2/src/util/domcore/NodeIterator.cpp
+++ b/media/libdrm/mobile2/src/util/domcore/NodeIterator.cpp
@@ -88,7 +88,7 @@
             node = node->getLastChild();

     } else {

         if (node == scopeNode)

-            node == NULL;

+            node = NULL;

         else

             node = node->getParentNode();

     }

diff --git a/opengl/libagl/egl.cpp b/opengl/libagl/egl.cpp
index cf66be3..0762ebf 100644
--- a/opengl/libagl/egl.cpp
+++ b/opengl/libagl/egl.cpp
@@ -384,6 +384,10 @@
 
 EGLBoolean egl_window_surface_v2_t::connect() 
 {
+    // we're intending to do software rendering
+    native_window_set_usage(nativeWindow, 
+            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN);
+
     // dequeue a buffer
     if (nativeWindow->dequeueBuffer(nativeWindow, &buffer) != NO_ERROR) {
         return setError(EGL_BAD_ALLOC, EGL_FALSE);
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 236d247..64b82eb 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -1363,34 +1363,32 @@
 EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
         const EGLint *attrib_list)
 {
-    EGLBoolean result = EGL_FALSE;
     if (!validate_display_surface(dpy, surface))
-        return result;
+        return EGL_FALSE;
 
     egl_display_t const * const dp = get_display(dpy);
     egl_surface_t const * const s = get_surface(surface);
 
     if (s->cnx->hooks->egl.eglLockSurfaceKHR) {
-        result = s->cnx->hooks->egl.eglLockSurfaceKHR(
+        return s->cnx->hooks->egl.eglLockSurfaceKHR(
                 dp->dpys[s->impl], s->surface, attrib_list);
     }
-    return result;
+    return setError(EGL_BAD_DISPLAY, EGL_FALSE);
 }
 
 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
 {
-    EGLBoolean result = EGL_FALSE;
     if (!validate_display_surface(dpy, surface))
-        return result;
+        return EGL_FALSE;
 
     egl_display_t const * const dp = get_display(dpy);
     egl_surface_t const * const s = get_surface(surface);
 
     if (s->cnx->hooks->egl.eglUnlockSurfaceKHR) {
-        result = s->cnx->hooks->egl.eglUnlockSurfaceKHR(
+        return s->cnx->hooks->egl.eglUnlockSurfaceKHR(
                 dp->dpys[s->impl], s->surface);
     }
-    return result;
+    return setError(EGL_BAD_DISPLAY, EGL_FALSE);
 }
 
 EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
@@ -1474,7 +1472,7 @@
 
      delete image;
 
-     return EGL_FALSE;
+     return EGL_TRUE;
 }
 
 
@@ -1493,7 +1491,7 @@
         return s->cnx->hooks->egl.eglSetSwapRectangleANDROID(dp->dpys[s->impl],
                 s->surface, left, top, width, height);
     }
-    return EGL_FALSE;
+    return setError(EGL_BAD_DISPLAY, NULL);
 }
 
 EGLClientBuffer eglGetRenderBufferANDROID(EGLDisplay dpy, EGLSurface draw)
@@ -1506,5 +1504,5 @@
         return s->cnx->hooks->egl.eglGetRenderBufferANDROID(dp->dpys[s->impl],
                 s->surface);
     }
-    return 0;
+    return setError(EGL_BAD_DISPLAY, (EGLClientBuffer*)0);
 }
diff --git a/packages/SettingsProvider/AndroidManifest.xml b/packages/SettingsProvider/AndroidManifest.xml
index d84572b..af0a1bd 100644
--- a/packages/SettingsProvider/AndroidManifest.xml
+++ b/packages/SettingsProvider/AndroidManifest.xml
@@ -2,6 +2,8 @@
         package="com.android.providers.settings"
         android:sharedUserId="android.uid.system">
 
+    <uses-permission android:name="android.permission.BACKUP_DATA" />
+
     <application android:allowClearUserData="false"
                  android:label="@string/app_label"
                  android:process="system"
diff --git a/packages/TtsService/src/android/tts/TtsService.java b/packages/TtsService/src/android/tts/TtsService.java
index 1b99d32..cd24727 100755
--- a/packages/TtsService/src/android/tts/TtsService.java
+++ b/packages/TtsService/src/android/tts/TtsService.java
@@ -172,10 +172,18 @@
     @Override
     public void onDestroy() {
         super.onDestroy();
+
+        // TODO replace the call to stopAll() with a method to clear absolutely all upcoming
+        // uses of the native synth, including synthesis to a file, and delete files for which
+        // synthesis was not complete.
+        stopAll("");
+
         // Don't hog the media player
         cleanUpPlayer();
 
-        sNativeSynth.shutdown();
+        if (sNativeSynth != null) {
+            sNativeSynth.shutdown();
+        }
         sNativeSynth = null;
 
         // Unregister all callbacks.
@@ -243,38 +251,70 @@
 
 
     private int setSpeechRate(String callingApp, int rate) {
-        if (isDefaultEnforced()) {
-            return sNativeSynth.setSpeechRate(getDefaultRate());
-        } else {
-            return sNativeSynth.setSpeechRate(rate);
+        int res = TextToSpeech.ERROR;
+        try {
+            if (isDefaultEnforced()) {
+                res = sNativeSynth.setSpeechRate(getDefaultRate());
+            } else {
+                res = sNativeSynth.setSpeechRate(rate);
+            }
+        } catch (NullPointerException e) {
+            // synth will become null during onDestroy()
+            res = TextToSpeech.ERROR;
         }
+        return res;
     }
 
 
     private int setPitch(String callingApp, int pitch) {
-        return sNativeSynth.setPitch(pitch);
+        int res = TextToSpeech.ERROR;
+        try {
+            res = sNativeSynth.setPitch(pitch);
+        } catch (NullPointerException e) {
+            // synth will become null during onDestroy()
+            res = TextToSpeech.ERROR;
+        }
+        return res;
     }
 
 
     private int isLanguageAvailable(String lang, String country, String variant) {
         //Log.v("TtsService", "TtsService.isLanguageAvailable(" + lang + ", " + country + ", " +variant+")");
-        return sNativeSynth.isLanguageAvailable(lang, country, variant);
+        int res = TextToSpeech.LANG_NOT_SUPPORTED;
+        try {
+            res = sNativeSynth.isLanguageAvailable(lang, country, variant);
+        } catch (NullPointerException e) {
+            // synth will become null during onDestroy()
+            res = TextToSpeech.LANG_NOT_SUPPORTED;
+        }
+        return res;
     }
 
 
     private String[] getLanguage() {
-        return sNativeSynth.getLanguage();
+        try {
+            return sNativeSynth.getLanguage();
+        } catch (Exception e) {
+            return null;
+        }
     }
 
 
     private int setLanguage(String callingApp, String lang, String country, String variant) {
         Log.v("TtsService", "TtsService.setLanguage(" + lang + ", " + country + ", " + variant + ")");
-        if (isDefaultEnforced()) {
-            return sNativeSynth.setLanguage(getDefaultLanguage(), getDefaultCountry(),
-                    getDefaultLocVariant());
-        } else {
-            return sNativeSynth.setLanguage(lang, country, variant);
+        int res = TextToSpeech.ERROR;
+        try {
+            if (isDefaultEnforced()) {
+                res = sNativeSynth.setLanguage(getDefaultLanguage(), getDefaultCountry(),
+                        getDefaultLocVariant());
+            } else {
+                res = sNativeSynth.setLanguage(lang, country, variant);
+            }
+        } catch (NullPointerException e) {
+            // synth will become null during onDestroy()
+            res = TextToSpeech.ERROR;
         }
+        return res;
     }
 
 
@@ -402,7 +442,12 @@
                 }
                 if ((mCurrentSpeechItem != null) &&
                      mCurrentSpeechItem.mCallingApp.equals(callingApp)) {
-                    result = sNativeSynth.stop();
+                    try {
+                        result = sNativeSynth.stop();
+                    } catch (NullPointerException e1) {
+                        // synth will become null during onDestroy()
+                        result = TextToSpeech.ERROR;
+                    }
                     mKillList.put(mCurrentSpeechItem, true);
                     if (mPlayer != null) {
                         try {
@@ -434,7 +479,8 @@
 
 
     /**
-     * Stops all speech output and removes any utterances still in the queue globally.
+     * Stops all speech output and removes any utterances still in the queue globally, except
+     * those intended to be synthesized to file.
      */
     private int stopAll(String callingApp) {
         int result = TextToSpeech.ERROR;
@@ -451,7 +497,12 @@
                 if ((mCurrentSpeechItem != null) &&
                     ((mCurrentSpeechItem.mType != SpeechItem.TEXT_TO_FILE) ||
                       mCurrentSpeechItem.mCallingApp.equals(callingApp))) {
-                    result = sNativeSynth.stop();
+                    try {
+                        result = sNativeSynth.stop();
+                    } catch (NullPointerException e1) {
+                        // synth will become null during onDestroy()
+                        result = TextToSpeech.ERROR;
+                    }
                     mKillList.put(mCurrentSpeechItem, true);
                     if (mPlayer != null) {
                         try {
@@ -591,7 +642,12 @@
                         if (speechRate.length() > 0){
                             setSpeechRate("", Integer.parseInt(speechRate));
                         }
-                        sNativeSynth.speak(speechItem.mText, streamType);
+                        try {
+                            sNativeSynth.speak(speechItem.mText, streamType);
+                        } catch (NullPointerException e) {
+                            // synth will become null during onDestroy()
+                            Log.v("TtsService", " null synth, can't speak");
+                        }
                     }
                 } catch (InterruptedException e) {
                     Log.e("TtsService", "TTS speakInternalOnly(): tryLock interrupted");
@@ -660,7 +716,12 @@
                         if (speechRate.length() > 0){
                             setSpeechRate("", Integer.parseInt(speechRate));
                         }
-                        sNativeSynth.synthesizeToFile(speechItem.mText, speechItem.mFilename);
+                        try {
+                            sNativeSynth.synthesizeToFile(speechItem.mText, speechItem.mFilename);
+                        } catch (NullPointerException e) {
+                            // synth will become null during onDestroy()
+                            Log.v("TtsService", " null synth, can't synthesize to file");
+                        }
                     }
                 } catch (InterruptedException e) {
                     Log.e("TtsService", "TTS synthToFileInternalOnly(): tryLock interrupted");
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index 78db6f9..5439f8b 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -1009,8 +1009,7 @@
         if (success) {
             // delete any hosts that didn't manage to get connected (should happen)
             // if it matters, they'll be reconnected.
-            final int N = mHosts.size();
-            for (int i=0; i<N; i++) {
+            for (int i=mHosts.size()-1; i>=0; i--) {
                 pruneHostLocked(mHosts.get(i));
             }
         } else {
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index 36dca7d..4eed7fe 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -31,6 +31,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageDataObserver;
 import android.content.pm.PackageInfo;
+import android.content.pm.PermissionInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageManager;
 import android.content.pm.Signature;
@@ -642,9 +643,12 @@
         List<PackageInfo> packages = mPackageManager.getInstalledPackages(flags);
         int N = packages.size();
         for (int a = N-1; a >= 0; a--) {
-            ApplicationInfo app = packages.get(a).applicationInfo;
+            PackageInfo pkg = packages.get(a);
+            ApplicationInfo app = pkg.applicationInfo;
             if (((app.flags&ApplicationInfo.FLAG_ALLOW_BACKUP) == 0)
-                    || app.backupAgentName == null) {
+                    || app.backupAgentName == null
+                    || (mPackageManager.checkPermission(android.Manifest.permission.BACKUP_DATA,
+                            pkg.packageName) != PackageManager.PERMISSION_GRANTED)) {
                 packages.remove(a);
             }
         }
@@ -899,6 +903,15 @@
             for (BackupRequest request : mQueue) {
                 Log.d(TAG, "starting agent for backup of " + request);
 
+                // Don't run backup, even if requested, if the target app does not have
+                // the requisite permission
+                if (mPackageManager.checkPermission(android.Manifest.permission.BACKUP_DATA,
+                        request.appInfo.packageName) != PackageManager.PERMISSION_GRANTED) {
+                    Log.w(TAG, "Skipping backup of unprivileged package "
+                            + request.appInfo.packageName);
+                    continue;
+                }
+
                 IBackupAgent agent = null;
                 int mode = (request.fullBackup)
                         ? IApplicationThread.BACKUP_MODE_FULL
@@ -1287,6 +1300,12 @@
 
             if (DEBUG) Log.d(TAG, "processOneRestore packageName=" + packageName);
 
+            // Don't restore to unprivileged packages
+            if (mPackageManager.checkPermission(android.Manifest.permission.BACKUP_DATA,
+                    packageName) != PackageManager.PERMISSION_GRANTED) {
+                Log.d(TAG, "Skipping restore of unprivileged package " + packageName);
+            }
+
             // !!! TODO: get the dirs from the transport
             File backupDataName = new File(mDataDir, packageName + ".restore");
             File newStateName = new File(mStateDir, packageName + ".new");
diff --git a/services/java/com/android/server/BatteryService.java b/services/java/com/android/server/BatteryService.java
index 45c1e5c..26fee89 100644
--- a/services/java/com/android/server/BatteryService.java
+++ b/services/java/com/android/server/BatteryService.java
@@ -44,8 +44,6 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 
-import com.android.internal.app.ShutdownThread;
-
 
 /**
  * <p>BatteryService monitors the charging status, and charge level of the device
@@ -176,6 +174,22 @@
         return mBatteryLevel;
     }
 
+    void systemReady() {
+        // check our power situation now that it is safe to display the shutdown dialog.
+        shutdownIfNoPower();
+    }
+
+    private final void shutdownIfNoPower() {
+        // shut down gracefully if our battery is critically low and we are not powered.
+        // wait until the system has booted before attempting to display the shutdown dialog.
+        if (mBatteryLevel == 0 && !isPowered() && ActivityManagerNative.isSystemReady()) {
+            Intent intent = new Intent(Intent.ACTION_REQUEST_SHUTDOWN);
+            intent.putExtra(Intent.EXTRA_KEY_CONFIRM, false);
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            mContext.startActivity(intent);
+        }
+    }
+
     private native void native_update();
 
     private synchronized final void update() {
@@ -184,11 +198,8 @@
         boolean logOutlier = false;
         long dischargeDuration = 0;
 
-        // shut down gracefully if our battery is critically low and we are not powered
-        if (mBatteryLevel == 0 && isPowered(0xffffffff)) {
-            ShutdownThread.shutdown(mContext, false);
-        }
-        
+        shutdownIfNoPower();
+
         mBatteryLevelCritical = mBatteryLevel <= CRITICAL_BATTERY_LEVEL;
         if (mAcOnline) {
             mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 62b839d..1c60058 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -30,48 +30,130 @@
 import android.net.wifi.WifiStateTracker;
 import android.os.Binder;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.provider.Settings;
+import android.text.TextUtils;
 import android.util.EventLog;
 import android.util.Log;
 
+import com.android.internal.telephony.Phone;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * @hide
  */
 public class ConnectivityService extends IConnectivityManager.Stub {
 
-    private static final boolean DBG = false;
+    private static final boolean DBG = true;
     private static final String TAG = "ConnectivityService";
 
     // Event log tags (must be in sync with event-log-tags)
     private static final int EVENTLOG_CONNECTIVITY_STATE_CHANGED = 50020;
 
+    // how long to wait before switching back to a radio's default network
+    private static final int RESTORE_DEFAULT_NETWORK_DELAY = 1 * 60 * 1000;
+    // system property that can override the above value
+    private static final String NETWORK_RESTORE_DELAY_PROP_NAME =
+            "android.telephony.apn-restore";
+
     /**
      * Sometimes we want to refer to the individual network state
      * trackers separately, and sometimes we just want to treat them
      * abstractly.
      */
     private NetworkStateTracker mNetTrackers[];
-    private WifiStateTracker mWifiStateTracker;
-    private MobileDataStateTracker mMobileDataStateTracker;
+
+    /**
+     * A per Net list of the PID's that requested access to the net
+     * used both as a refcount and for per-PID DNS selection
+     */
+    private List mNetRequestersPids[];
+
     private WifiWatchdogService mWifiWatchdogService;
 
+    // priority order of the nettrackers
+    // (excluding dynamically set mNetworkPreference)
+    // TODO - move mNetworkTypePreference into this
+    private int[] mPriorityList;
+
     private Context mContext;
     private int mNetworkPreference;
-    private NetworkStateTracker mActiveNetwork;
+    private int mActiveDefaultNetwork = -1;
 
     private int mNumDnsEntries;
-    private static int sDnsChangeCounter;
 
     private boolean mTestMode;
     private static ConnectivityService sServiceInstance;
 
+    private Handler mHandler;
+
+    // list of DeathRecipients used to make sure features are turned off when
+    // a process dies
+    private List mFeatureUsers;
+
+    private class NetworkAttributes {
+        /**
+         * Class for holding settings read from resources.
+         */
+        public String mName;
+        public int mType;
+        public int mRadio;
+        public int mPriority;
+        public NetworkAttributes(String init) {
+            String fragments[] = init.split(",");
+            mName = fragments[0].toLowerCase();
+            if (fragments[1].toLowerCase().equals("wifi")) {
+                mRadio = ConnectivityManager.TYPE_WIFI;
+            } else {
+                mRadio = ConnectivityManager.TYPE_MOBILE;
+            }
+            if (mName.equals("default")) {
+                mType = mRadio;
+            } else if (mName.equals("mms")) {
+                mType = ConnectivityManager.TYPE_MOBILE_MMS;
+            } else if (mName.equals("supl")) {
+                mType = ConnectivityManager.TYPE_MOBILE_SUPL;
+            } else if (mName.equals("dun")) {
+                mType = ConnectivityManager.TYPE_MOBILE_DUN;
+            } else if (mName.equals("hipri")) {
+                mType = ConnectivityManager.TYPE_MOBILE_HIPRI;
+            }
+            mPriority = Integer.parseInt(fragments[2]);
+        }
+        public boolean isDefault() {
+            return (mType == mRadio);
+        }
+    }
+    NetworkAttributes[] mNetAttributes;
+
+    private class RadioAttributes {
+        public String mName;
+        public int mPriority;
+        public int mSimultaneity;
+        public int mType;
+        public RadioAttributes(String init) {
+            String fragments[] = init.split(",");
+            mName = fragments[0].toLowerCase();
+            mPriority = Integer.parseInt(fragments[1]);
+            mSimultaneity = Integer.parseInt(fragments[2]);
+            if (mName.equals("wifi")) {
+                mType = ConnectivityManager.TYPE_WIFI;
+            } else {
+                mType = ConnectivityManager.TYPE_MOBILE;
+            }
+        }
+    }
+    RadioAttributes[] mRadioAttributes;
+
     private static class ConnectivityThread extends Thread {
         private Context mContext;
 
@@ -118,11 +200,54 @@
     private ConnectivityService(Context context) {
         if (DBG) Log.v(TAG, "ConnectivityService starting up");
         mContext = context;
-        mNetTrackers = new NetworkStateTracker[2];
-        Handler handler = new MyHandler();
+        mNetTrackers = new NetworkStateTracker[
+                ConnectivityManager.MAX_NETWORK_TYPE+1];
+        mHandler = new MyHandler();
 
         mNetworkPreference = getPersistedNetworkPreference();
 
+        // Load device network attributes from resources
+        mNetAttributes = new NetworkAttributes[
+                ConnectivityManager.MAX_NETWORK_TYPE+1];
+        mRadioAttributes = new RadioAttributes[
+                ConnectivityManager.MAX_RADIO_TYPE+1];
+        String[] naStrings = context.getResources().getStringArray(
+                com.android.internal.R.array.networkAttributes);
+        // TODO - what if the setting has gaps/unknown types?
+        for (String a : naStrings) {
+            NetworkAttributes n = new NetworkAttributes(a);
+            mNetAttributes[n.mType] = n;
+        }
+        String[] raStrings = context.getResources().getStringArray(
+                com.android.internal.R.array.radioAttributes);
+        for (String a : raStrings) {
+            RadioAttributes r = new RadioAttributes(a);
+            mRadioAttributes[r.mType] = r;
+        }
+
+        // high priority first
+        mPriorityList = new int[naStrings.length];
+        {
+            int priority = 0; //lowest
+            int nextPos = naStrings.length-1;
+            while (nextPos>-1) {
+                for (int i = 0; i < mNetAttributes.length; i++) {
+                    if(mNetAttributes[i].mPriority == priority) {
+                        mPriorityList[nextPos--] = i;
+                    }
+                }
+                priority++;
+            }
+        }
+
+        mNetRequestersPids =
+                new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE+1];
+        for (int i=0; i<=ConnectivityManager.MAX_NETWORK_TYPE; i++) {
+            mNetRequestersPids[i] = new ArrayList();
+        }
+
+        mFeatureUsers = new ArrayList();
+
         /*
          * Create the network state trackers for Wi-Fi and mobile
          * data. Maybe this could be done with a factory class,
@@ -131,15 +256,36 @@
          * to change very often.
          */
         if (DBG) Log.v(TAG, "Starting Wifi Service.");
-        mWifiStateTracker = new WifiStateTracker(context, handler);
-        WifiService wifiService = new WifiService(context, mWifiStateTracker);
+        WifiStateTracker wst = new WifiStateTracker(context, mHandler);
+        WifiService wifiService = new WifiService(context, wst);
         ServiceManager.addService(Context.WIFI_SERVICE, wifiService);
-        mNetTrackers[ConnectivityManager.TYPE_WIFI] = mWifiStateTracker;
+        mNetTrackers[ConnectivityManager.TYPE_WIFI] = wst;
 
-        mMobileDataStateTracker = new MobileDataStateTracker(context, handler);
-        mNetTrackers[ConnectivityManager.TYPE_MOBILE] = mMobileDataStateTracker;
+        mNetTrackers[ConnectivityManager.TYPE_MOBILE] =
+                new MobileDataStateTracker(context, mHandler,
+                ConnectivityManager.TYPE_MOBILE, Phone.APN_TYPE_DEFAULT,
+                "MOBILE");
 
-        mActiveNetwork = null;
+        mNetTrackers[ConnectivityManager.TYPE_MOBILE_MMS] =
+                new MobileDataStateTracker(context, mHandler,
+                ConnectivityManager.TYPE_MOBILE_MMS, Phone.APN_TYPE_MMS,
+                "MOBILE_MMS");
+
+        mNetTrackers[ConnectivityManager.TYPE_MOBILE_SUPL] =
+                new MobileDataStateTracker(context, mHandler,
+                ConnectivityManager.TYPE_MOBILE_SUPL, Phone.APN_TYPE_SUPL,
+                "MOBILE_SUPL");
+
+        mNetTrackers[ConnectivityManager.TYPE_MOBILE_DUN] =
+                new MobileDataStateTracker(context, mHandler,
+                ConnectivityManager.TYPE_MOBILE_DUN, Phone.APN_TYPE_DUN,
+                "MOBILE_DUN");
+
+        mNetTrackers[ConnectivityManager.TYPE_MOBILE_HIPRI] =
+                new MobileDataStateTracker(context, mHandler,
+                ConnectivityManager.TYPE_MOBILE_HIPRI, Phone.APN_TYPE_HIPRI,
+                "MOBILE_HIPRI");
+
         mNumDnsEntries = 0;
 
         mTestMode = SystemProperties.get("cm.test.mode").equals("true")
@@ -149,8 +295,7 @@
             t.startMonitoring();
 
         // Constructing this starts it too
-        mWifiWatchdogService = new WifiWatchdogService(context,
-                mWifiStateTracker);
+        mWifiWatchdogService = new WifiWatchdogService(context, wst);
     }
 
     /**
@@ -159,7 +304,8 @@
      */
     public synchronized void setNetworkPreference(int preference) {
         enforceChangePermission();
-        if (ConnectivityManager.isNetworkTypeValid(preference)) {
+        if (ConnectivityManager.isNetworkTypeValid(preference) &&
+                mNetAttributes[preference].isDefault()) {
             if (mNetworkPreference != preference) {
                 persistNetworkPreference(preference);
                 mNetworkPreference = preference;
@@ -199,23 +345,16 @@
      * (see {@link #handleDisconnect(NetworkInfo)}).
      */
     private void enforcePreference() {
-        if (mActiveNetwork == null)
+        if (mNetTrackers[mNetworkPreference].getNetworkInfo().isConnected())
             return;
 
-        for (NetworkStateTracker t : mNetTrackers) {
-            if (t == mActiveNetwork) {
-                int netType = t.getNetworkInfo().getType();
-                int otherNetType = ((netType == ConnectivityManager.TYPE_WIFI) ?
-                        ConnectivityManager.TYPE_MOBILE :
-                        ConnectivityManager.TYPE_WIFI);
+        if (!mNetTrackers[mNetworkPreference].isAvailable())
+            return;
 
-                if (t.getNetworkInfo().getType() != mNetworkPreference) {
-                    NetworkStateTracker otherTracker =
-                            mNetTrackers[otherNetType];
-                    if (otherTracker.isAvailable()) {
-                        teardown(t);
-                    }
-                }
+        for (int t=0; t <= ConnectivityManager.MAX_RADIO_TYPE; t++) {
+            if (t != mNetworkPreference &&
+                    mNetTrackers[t].getNetworkInfo().isConnected()) {
+                teardown(mNetTrackers[t]);
             }
         }
     }
@@ -238,9 +377,16 @@
      */
     public NetworkInfo getActiveNetworkInfo() {
         enforceAccessPermission();
-        for (NetworkStateTracker t : mNetTrackers) {
+        for (int type=0; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) {
+            if (!mNetAttributes[type].isDefault()) {
+                continue;
+            }
+            NetworkStateTracker t = mNetTrackers[type];
             NetworkInfo info = t.getNetworkInfo();
             if (info.isConnected()) {
+                if (DBG && type != mActiveDefaultNetwork) Log.e(TAG,
+                        "connected default network is not " +
+                        "mActiveDefaultNetwork!");
                 return info;
             }
         }
@@ -285,30 +431,189 @@
         return tracker != null && tracker.setRadio(turnOn);
     }
 
-    public int startUsingNetworkFeature(int networkType, String feature) {
+    private class FeatureUser implements IBinder.DeathRecipient {
+        int mNetworkType;
+        String mFeature;
+        IBinder mBinder;
+        int mPid;
+        int mUid;
+
+        FeatureUser(int type, String feature, IBinder binder) {
+            super();
+            mNetworkType = type;
+            mFeature = feature;
+            mBinder = binder;
+            mPid = getCallingPid();
+            mUid = getCallingUid();
+            try {
+                mBinder.linkToDeath(this, 0);
+            } catch (RemoteException e) {
+                binderDied();
+            }
+        }
+
+        void unlinkDeathRecipient() {
+            mBinder.unlinkToDeath(this, 0);
+        }
+
+        public void binderDied() {
+            Log.d(TAG, "ConnectivityService FeatureUser binderDied(" +
+                    mNetworkType + ", " + mFeature + ", " + mBinder);
+            stopUsingNetworkFeature(mNetworkType, mFeature, mPid, mUid);
+        }
+
+    }
+
+    public int startUsingNetworkFeature(int networkType, String feature,
+            IBinder binder) {
+        if (DBG) {
+            Log.d(TAG, "startUsingNetworkFeature for net " + networkType +
+                    ": " + feature);
+        }
         enforceChangePermission();
         if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
-            return -1;
+            return Phone.APN_REQUEST_FAILED;
         }
-        NetworkStateTracker tracker = mNetTrackers[networkType];
-        if (tracker != null) {
-            return tracker.startUsingNetworkFeature(feature, getCallingPid(),
-                    getCallingUid());
+
+        synchronized (mFeatureUsers) {
+            mFeatureUsers.add(new FeatureUser(networkType, feature, binder));
         }
-        return -1;
+
+        // TODO - move this into the MobileDataStateTracker
+        int usedNetworkType = networkType;
+        if(networkType == ConnectivityManager.TYPE_MOBILE) {
+            if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
+                usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS;
+            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
+                usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL;
+            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN)) {
+                usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN;
+            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
+                usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
+            }
+        }
+        NetworkStateTracker network = mNetTrackers[usedNetworkType];
+        if (network != null) {
+            if (usedNetworkType != networkType) {
+                Integer currentPid = new Integer(getCallingPid());
+
+                NetworkStateTracker radio = mNetTrackers[networkType];
+                NetworkInfo ni = network.getNetworkInfo();
+
+                if (ni.isAvailable() == false) {
+                    if (DBG) Log.d(TAG, "special network not available");
+                    return Phone.APN_TYPE_NOT_AVAILABLE;
+                }
+
+                if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) {
+                    // this gets used for per-pid dns when connected
+                    mNetRequestersPids[usedNetworkType].add(currentPid);
+                }
+
+                if (ni.isConnectedOrConnecting() == true) {
+                    if (ni.isConnected() == true) {
+                        // add the pid-specific dns
+                        handleDnsConfigurationChange();
+                        if (DBG) Log.d(TAG, "special network already active");
+                        return Phone.APN_ALREADY_ACTIVE;
+                    }
+                    if (DBG) Log.d(TAG, "special network already connecting");
+                    return Phone.APN_REQUEST_STARTED;
+                }
+
+                // check if the radio in play can make another contact
+                // assume if cannot for now
+
+                // since we have to drop the default on this radio, setup
+                // an automatic event to switch back
+                if(mHandler.hasMessages(NetworkStateTracker.
+                        EVENT_RESTORE_DEFAULT_NETWORK, radio) ||
+                        radio.getNetworkInfo().isConnectedOrConnecting()) {
+                    mHandler.removeMessages(NetworkStateTracker.
+                            EVENT_RESTORE_DEFAULT_NETWORK,
+                            radio);
+                    mHandler.sendMessageDelayed(mHandler.obtainMessage(
+                            NetworkStateTracker.EVENT_RESTORE_DEFAULT_NETWORK,
+                            radio), getRestoreDefaultNetworkDelay());
+                }
+                if (DBG) Log.d(TAG, "reconnecting to special network");
+                network.reconnect();
+                return Phone.APN_REQUEST_STARTED;
+            } else {
+                return network.startUsingNetworkFeature(feature,
+                        getCallingPid(), getCallingUid());
+            }
+        }
+        return Phone.APN_TYPE_NOT_AVAILABLE;
     }
 
     public int stopUsingNetworkFeature(int networkType, String feature) {
+        return stopUsingNetworkFeature(networkType, feature, getCallingPid(),
+                getCallingUid());
+    }
+
+    private int stopUsingNetworkFeature(int networkType, String feature,
+            int pid, int uid) {
+        if (DBG) {
+            Log.d(TAG, "stopUsingNetworkFeature for net " + networkType +
+                    ": " + feature);
+        }
         enforceChangePermission();
         if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
             return -1;
         }
-        NetworkStateTracker tracker = mNetTrackers[networkType];
-        if (tracker != null) {
-            return tracker.stopUsingNetworkFeature(feature, getCallingPid(),
-                    getCallingUid());
+
+        synchronized (mFeatureUsers) {
+            for (int i=0; i < mFeatureUsers.size(); i++) {
+                FeatureUser u = (FeatureUser)mFeatureUsers.get(i);
+                if (uid == u.mUid && pid == u.mPid &&
+                        networkType == u.mNetworkType &&
+                        TextUtils.equals(feature, u.mFeature)) {
+                    u.unlinkDeathRecipient();
+                    mFeatureUsers.remove(i);
+                    break;
+                }
+            }
         }
-        return -1;
+
+        // TODO - move to MobileDataStateTracker
+        int usedNetworkType = networkType;
+        if (networkType == ConnectivityManager.TYPE_MOBILE) {
+            if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
+                usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS;
+            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
+                usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL;
+            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN)) {
+                usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN;
+            } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) {
+                usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI;
+            }
+        }
+        NetworkStateTracker tracker =  mNetTrackers[usedNetworkType];
+        if(usedNetworkType != networkType) {
+            Integer currentPid = new Integer(pid);
+            if (mNetRequestersPids[usedNetworkType].remove(currentPid)) {
+                reassessPidDns(pid, true);
+            }
+            if (mNetRequestersPids[usedNetworkType].size() != 0) {
+                if (DBG) Log.d(TAG, "not tearing down special network - " +
+                        "others still using it");
+                return 1;
+            }
+
+            tracker.teardown();
+            NetworkStateTracker radio = mNetTrackers[networkType];
+            // Check if we want to revert to the default
+            if (mHandler.hasMessages(NetworkStateTracker.
+                    EVENT_RESTORE_DEFAULT_NETWORK, radio)) {
+                mHandler.removeMessages(NetworkStateTracker.
+                        EVENT_RESTORE_DEFAULT_NETWORK, radio);
+                radio.reconnect();
+            }
+            return 1;
+        } else {
+            return tracker.stopUsingNetworkFeature(feature, pid, uid);
+        }
     }
 
     /**
@@ -337,7 +642,8 @@
         if (getNumConnectedNetworks() > 1) {
             return tracker.requestRouteToHost(hostAddress);
         } else {
-            return tracker.getNetworkInfo().getType() == networkType;
+            return (mNetAttributes[networkType].isDefault() &&
+                    tracker.getNetworkInfo().isConnected());
         }
     }
 
@@ -402,45 +708,26 @@
     private void handleDisconnect(NetworkInfo info) {
 
         if (DBG) Log.v(TAG, "Handle DISCONNECT for " + info.getTypeName());
+        int prevNetType = info.getType();
 
-        mNetTrackers[info.getType()].setTeardownRequested(false);
+        mNetTrackers[prevNetType].setTeardownRequested(false);
         /*
          * If the disconnected network is not the active one, then don't report
          * this as a loss of connectivity. What probably happened is that we're
          * getting the disconnect for a network that we explicitly disabled
          * in accordance with network preference policies.
          */
-        if (mActiveNetwork == null ||
-                info.getType() != mActiveNetwork.getNetworkInfo().getType())
-            return;
-
-        NetworkStateTracker newNet;
-        if (info.getType() == ConnectivityManager.TYPE_MOBILE) {
-            newNet = mWifiStateTracker;
-        } else /* info().getType() == TYPE_WIFI */ {
-            newNet = mMobileDataStateTracker;
-        }
-
-        /**
-         * See if the other network is available to fail over to.
-         * If is not available, we enable it anyway, so that it
-         * will be able to connect when it does become available,
-         * but we report a total loss of connectivity rather than
-         * report that we are attempting to fail over.
-         */
-        NetworkInfo switchTo = null;
-        if (newNet.isAvailable()) {
-            mActiveNetwork = newNet;
-            switchTo = newNet.getNetworkInfo();
-            switchTo.setFailover(true);
-            if (!switchTo.isConnectedOrConnecting()) {
-                newNet.reconnect();
+        if (!mNetAttributes[prevNetType].isDefault()) {
+            List pids = mNetRequestersPids[prevNetType];
+            for (int i = 0; i<pids.size(); i++) {
+                Integer pid = (Integer)pids.get(i);
+                // will remove them because the net's no longer connected
+                // need to do this now as only now do we know the pids and
+                // can properly null things that are no longer referenced.
+                reassessPidDns(pid.intValue(), false);
             }
-        } else {
-            newNet.reconnect();
         }
 
-        boolean otherNetworkConnected = false;
         Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
         intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
         if (info.isFailover()) {
@@ -454,33 +741,92 @@
             intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
                     info.getExtraInfo());
         }
-        if (switchTo != null) {
-            otherNetworkConnected = switchTo.isConnected();
-            if (DBG) {
-                if (otherNetworkConnected) {
-                    Log.v(TAG, "Switching to already connected " +
-                            switchTo.getTypeName());
-                } else {
-                    Log.v(TAG, "Attempting to switch to " +
-                            switchTo.getTypeName());
+
+        /*
+         * If this is a default network, check if other defaults are available
+         * or active
+         */
+        NetworkStateTracker newNet = null;
+        if (mNetAttributes[prevNetType].isDefault()) {
+            if (DBG) Log.d(TAG, "disconnecting a default network");
+            if (mActiveDefaultNetwork == prevNetType) {
+                mActiveDefaultNetwork = -1;
+            }
+
+            int newType = -1;
+            int newPriority = -1;
+            for (int checkType=0; checkType <=
+                    ConnectivityManager.MAX_NETWORK_TYPE; checkType++) {
+                if (checkType == prevNetType) {
+                    continue;
+                }
+                if (mNetAttributes[checkType].isDefault()) {
+                    /* TODO - if we have multiple nets we could use
+                     * we may want to put more thought into which we choose
+                     */
+                    if (checkType == mNetworkPreference) {
+                        newType = checkType;
+                        break;
+                    }
+                    if (mRadioAttributes[mNetAttributes[checkType].mRadio].
+                            mPriority > newPriority) {
+                        newType = checkType;
+                        newPriority = mRadioAttributes[mNetAttributes[newType].
+                                mRadio].mPriority;
+                    }
                 }
             }
-            intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO,
-                    switchTo);
-        } else {
-            intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
+
+            if (newType != -1) {
+                newNet = mNetTrackers[newType];
+                /**
+                 * See if the other network is available to fail over to.
+                 * If is not available, we enable it anyway, so that it
+                 * will be able to connect when it does become available,
+                 * but we report a total loss of connectivity rather than
+                 * report that we are attempting to fail over.
+                 */
+                if (newNet.isAvailable()) {
+                    NetworkInfo switchTo = newNet.getNetworkInfo();
+                    switchTo.setFailover(true);
+                    if (!switchTo.isConnectedOrConnecting()) {
+                        newNet.reconnect();
+                    }
+                    if (DBG) {
+                        if (switchTo.isConnected()) {
+                            Log.v(TAG, "Switching to already connected " +
+                                    switchTo.getTypeName());
+                        } else {
+                            Log.v(TAG, "Attempting to switch to " +
+                                    switchTo.getTypeName());
+                        }
+                    }
+                    intent.putExtra(ConnectivityManager.
+                            EXTRA_OTHER_NETWORK_INFO, switchTo);
+                } else {
+                    newNet.reconnect();
+                }
+            } else {
+                intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY,
+                        true);
+            }
         }
+
+        // do this before we broadcast the change
+        handleConnectivityChange();
+
         if (DBG) Log.v(TAG, "Sending DISCONNECT bcast for " +
                 info.getTypeName() +
-                (switchTo == null ? "" : " other=" + switchTo.getTypeName()));
+                (newNet == null || !newNet.isAvailable() ? "" : " other=" +
+                newNet.getNetworkInfo().getTypeName()));
 
         mContext.sendStickyBroadcast(intent);
         /*
          * If the failover network is already connected, then immediately send
          * out a followup broadcast indicating successful failover
          */
-        if (switchTo != null && otherNetworkConnected)
-            sendConnectedBroadcast(switchTo);
+        if (newNet != null && newNet.getNetworkInfo().isConnected())
+            sendConnectedBroadcast(newNet.getNetworkInfo());
     }
 
     private void sendConnectedBroadcast(NetworkInfo info) {
@@ -506,93 +852,85 @@
      */
     private void handleConnectionFailure(NetworkInfo info) {
         mNetTrackers[info.getType()].setTeardownRequested(false);
-        if (getActiveNetworkInfo() == null) {
-            String reason = info.getReason();
-            String extraInfo = info.getExtraInfo();
 
-            if (DBG) {
-                String reasonText;
-                if (reason == null) {
-                    reasonText = ".";
-                } else {
-                    reasonText = " (" + reason + ").";
-                }
-                Log.v(TAG, "Attempt to connect to " + info.getTypeName() +
-                        " failed" + reasonText);
-            }
+        String reason = info.getReason();
+        String extraInfo = info.getExtraInfo();
 
-            Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
-            intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
-            intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
-            if (reason != null) {
-                intent.putExtra(ConnectivityManager.EXTRA_REASON, reason);
+        if (DBG) {
+            String reasonText;
+            if (reason == null) {
+                reasonText = ".";
+            } else {
+                reasonText = " (" + reason + ").";
             }
-            if (extraInfo != null) {
-                intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO,
-                        extraInfo);
-            }
-            if (info.isFailover()) {
-                intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
-                info.setFailover(false);
-            }
-            mContext.sendStickyBroadcast(intent);
+            Log.v(TAG, "Attempt to connect to " + info.getTypeName() +
+                    " failed" + reasonText);
         }
+
+        Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
+        intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
+        if (getActiveNetworkInfo() == null) {
+            intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
+        }
+        if (reason != null) {
+            intent.putExtra(ConnectivityManager.EXTRA_REASON, reason);
+        }
+        if (extraInfo != null) {
+            intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, extraInfo);
+        }
+        if (info.isFailover()) {
+            intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
+            info.setFailover(false);
+        }
+        mContext.sendStickyBroadcast(intent);
     }
 
     private void handleConnect(NetworkInfo info) {
-        if (DBG) Log.v(TAG, "Handle CONNECT for " + info.getTypeName());
+        if (DBG) Log.d(TAG, "Handle CONNECT for " + info.getTypeName());
+
+        int type = info.getType();
 
         // snapshot isFailover, because sendConnectedBroadcast() resets it
         boolean isFailover = info.isFailover();
-        NetworkStateTracker thisNet = mNetTrackers[info.getType()];
-        NetworkStateTracker deadnet = null;
-        NetworkStateTracker otherNet;
-        if (info.getType() == ConnectivityManager.TYPE_MOBILE) {
-            otherNet = mWifiStateTracker;
-        } else /* info().getType() == TYPE_WIFI */ {
-            otherNet = mMobileDataStateTracker;
-        }
-        /*
-         * Check policy to see whether we are connected to a non-preferred
-         * network that now needs to be torn down.
-         */
-        NetworkInfo wifiInfo = mWifiStateTracker.getNetworkInfo();
-        NetworkInfo mobileInfo = mMobileDataStateTracker.getNetworkInfo();
-        if (wifiInfo.isConnected() && mobileInfo.isConnected()) {
-            if (mNetworkPreference == ConnectivityManager.TYPE_WIFI)
-                deadnet = mMobileDataStateTracker;
-            else
-                deadnet = mWifiStateTracker;
-        }
+        NetworkStateTracker thisNet = mNetTrackers[type];
 
-        boolean toredown = false;
+        // if this is a default net and other default is running
+        // kill the one not preferred
+        if (mNetAttributes[type].isDefault()) {
+            if (DBG) Log.d(TAG, "connecting to a default network");
+            if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != type) {
+                if ((type != mNetworkPreference &&
+                        mNetAttributes[mActiveDefaultNetwork].mPriority >
+                        mNetAttributes[type].mPriority) ||
+                        mNetworkPreference == mActiveDefaultNetwork) {
+                        // don't accept this one
+                        if (DBG) Log.v(TAG, "Not broadcasting CONNECT_ACTION " +
+                                "to torn down network " + info.getTypeName());
+                        teardown(thisNet);
+                        return;
+                } else {
+                    // tear down the other
+                    NetworkStateTracker otherNet =
+                            mNetTrackers[mActiveDefaultNetwork];
+                    if (DBG) Log.v(TAG, "Policy requires " +
+                            otherNet.getNetworkInfo().getTypeName() +
+                            " teardown");
+                    if (!teardown(otherNet)) {
+                        Log.e(TAG, "Network declined teardown request");
+                        return;
+                    }
+                    if (isFailover) {
+                        otherNet.releaseWakeLock();
+                    }
+                }
+            }
+            mActiveDefaultNetwork = type;
+        }
         thisNet.setTeardownRequested(false);
-        if (!mTestMode && deadnet != null) {
-            if (DBG) Log.v(TAG, "Policy requires " +
-                  deadnet.getNetworkInfo().getTypeName() + " teardown");
-            toredown = teardown(deadnet);
-            if (DBG && !toredown) {
-                Log.d(TAG, "Network declined teardown request");
-            }
-        }
-
-        /*
-         * Note that if toredown is true, deadnet cannot be null, so there is
-         * no danger of a null pointer exception here..
-         */
-        if (!toredown || deadnet.getNetworkInfo().getType() != info.getType()) {
-            mActiveNetwork = thisNet;
-            if (DBG) Log.v(TAG, "Sending CONNECT bcast for " +
-                    info.getTypeName());
-            thisNet.updateNetworkSettings();
-            sendConnectedBroadcast(info);
-            if (isFailover) {
-                otherNet.releaseWakeLock();
-            }
-        } else {
-            if (DBG) Log.v(TAG, "Not broadcasting CONNECT_ACTION to torn " +
-                    "down network " + info.getTypeName());
-        }
+        if (DBG) Log.d(TAG, "Sending CONNECT bcast for " + info.getTypeName());
+        thisNet.updateNetworkSettings();
+        handleConnectivityChange();
+        sendConnectedBroadcast(info);
     }
 
     private void handleScanResultsAvailable(NetworkInfo info) {
@@ -626,60 +964,148 @@
      * table entries exist.
      */
     private void handleConnectivityChange() {
+        if (DBG) Log.d(TAG, "handleConnectivityChange");
         /*
+         * If a non-default network is enabled, add the host routes that
+         * will allow it's DNS servers to be accessed.  Only 
          * If both mobile and wifi are enabled, add the host routes that
          * will allow MMS traffic to pass on the mobile network. But
          * remove the default route for the mobile network, so that there
          * will be only one default route, to ensure that all traffic
          * except MMS will travel via Wi-Fi.
          */
-        int numConnectedNets = handleConfigurationChange();
-        if (numConnectedNets > 1) {
-            mMobileDataStateTracker.addPrivateRoutes();
-            mMobileDataStateTracker.removeDefaultRoute();
-        } else if (mMobileDataStateTracker.getNetworkInfo().isConnected()) {
-            mMobileDataStateTracker.removePrivateRoutes();
-            mMobileDataStateTracker.restoreDefaultRoute();
+        handleDnsConfigurationChange();
+
+        for (int netType : mPriorityList) {
+            if (mNetTrackers[netType].getNetworkInfo().isConnected()) {
+                if (mNetAttributes[netType].isDefault()) {
+                    mNetTrackers[netType].addDefaultRoute();
+                } else {
+                    mNetTrackers[netType].addPrivateDnsRoutes();
+                }
+            } else {
+                if (mNetAttributes[netType].isDefault()) {
+                    mNetTrackers[netType].removeDefaultRoute();
+                } else {
+                    mNetTrackers[netType].removePrivateDnsRoutes();
+                }
+            }
         }
     }
 
-    private int handleConfigurationChange() {
-        /*
-         * Set DNS properties. Always put Wi-Fi entries at the front of
-         * the list if it is active.
-         */
-        int index = 1;
-        String lastDns = "";
-        int numConnectedNets = 0;
-        int incrValue = ConnectivityManager.TYPE_MOBILE -
-                ConnectivityManager.TYPE_WIFI;
-        int stopValue = ConnectivityManager.TYPE_MOBILE + incrValue;
-
-        for (int netType = ConnectivityManager.TYPE_WIFI; netType != stopValue;
-                netType += incrValue) {
-            NetworkStateTracker nt = mNetTrackers[netType];
+    /**
+     * Adjust the per-process dns entries (net.dns<x>.<pid>) based
+     * on the highest priority active net which this process requested.
+     * If there aren't any, clear it out
+     */
+    private void reassessPidDns(int myPid, boolean doBump)
+    {
+        if (DBG) Log.d(TAG, "reassessPidDns for pid " + myPid);
+        for(int i : mPriorityList) {
+            if (mNetAttributes[i].isDefault()) {
+                continue;
+            }
+            NetworkStateTracker nt = mNetTrackers[i];
             if (nt.getNetworkInfo().isConnected() &&
                     !nt.isTeardownRequested()) {
-                ++numConnectedNets;
+                List pids = mNetRequestersPids[i];
+                for (int j=0; j<pids.size(); j++) {
+                    Integer pid = (Integer)pids.get(j);
+                    if (pid.intValue() == myPid) {
+                        String[] dnsList = nt.getNameServers();
+                        writePidDns(dnsList, myPid);
+                        if (doBump) {
+                            bumpDns();
+                        }
+                        return;
+                    }
+                }
+           }
+        }
+        // nothing found - delete
+        for (int i = 1; ; i++) {
+            String prop = "net.dns" + i + "." + myPid;
+            if (SystemProperties.get(prop).length() == 0) {
+                if (doBump) {
+                    bumpDns();
+                }
+                return;
+            }
+            SystemProperties.set(prop, "");
+        }
+    }
+
+    private void writePidDns(String[] dnsList, int pid) {
+        int j = 1;
+        for (String dns : dnsList) {
+            if (dns != null && !TextUtils.equals(dns, "0.0.0.0")) {
+                SystemProperties.set("net.dns" + j++ + "." + pid, dns);
+            }
+        }
+    }
+
+    private void bumpDns() {
+        /*
+         * Bump the property that tells the name resolver library to reread
+         * the DNS server list from the properties.
+         */
+        String propVal = SystemProperties.get("net.dnschange");
+        int n = 0;
+        if (propVal.length() != 0) {
+            try {
+                n = Integer.parseInt(propVal);
+            } catch (NumberFormatException e) {}
+        }
+        SystemProperties.set("net.dnschange", "" + (n+1));
+    }
+
+    private void handleDnsConfigurationChange() {
+        if (DBG) Log.d(TAG, "handleDnsConfig Change");
+        // add default net's dns entries
+        for (int x = mPriorityList.length-1; x>= 0; x--) {
+            int netType = mPriorityList[x];
+            NetworkStateTracker nt = mNetTrackers[netType];
+            if (DBG) Log.d(TAG, " checking " + nt);
+            if (nt != null && nt.getNetworkInfo().isConnected() &&
+                    !nt.isTeardownRequested()) {
+                if (DBG) Log.d(TAG, "  connected");
                 String[] dnsList = nt.getNameServers();
-                for (int i = 0; i < dnsList.length && dnsList[i] != null; i++) {
-                    // skip duplicate entries
-                    if (!dnsList[i].equals(lastDns)) {
-                        SystemProperties.set("net.dns" + index++, dnsList[i]);
-                        lastDns = dnsList[i];
+                if (mNetAttributes[netType].isDefault()) {
+                    int j = 1;
+                    for (String dns : dnsList) {
+                        if (dns != null && !TextUtils.equals(dns, "0.0.0.0")) {
+                            SystemProperties.set("net.dns" + j++, dns);
+                        }
+                    }
+                    for (int k=j ; k<mNumDnsEntries; k++) {
+                        SystemProperties.set("net.dns" + j, "");
+                    }
+                    mNumDnsEntries = j;
+                } else {
+                    // set per-pid dns for attached secondary nets
+                    List pids = mNetRequestersPids[netType];
+                    for (int y=0; y< pids.size(); y++) {
+                        Integer pid = (Integer)pids.get(y);
+                        writePidDns(dnsList, pid.intValue());
                     }
                 }
             }
         }
-        // Null out any DNS properties that are no longer used
-        for (int i = index; i <= mNumDnsEntries; i++) {
-            SystemProperties.set("net.dns" + i, "");
+
+        bumpDns();
+    }
+
+    private int getRestoreDefaultNetworkDelay() {
+        String restoreDefaultNetworkDelayStr = SystemProperties.get(
+                NETWORK_RESTORE_DELAY_PROP_NAME);
+        if(restoreDefaultNetworkDelayStr != null &&
+                restoreDefaultNetworkDelayStr.length() != 0) {
+            try {
+                return Integer.valueOf(restoreDefaultNetworkDelayStr);
+            } catch (NumberFormatException e) {
+            }
         }
-        mNumDnsEntries = index - 1;
-        // Notify the name resolver library of the change
-        SystemProperties.set("net.dnschange",
-                String.valueOf(sDnsChangeCounter++));
-        return numConnectedNets;
+        return RESTORE_DEFAULT_NETWORK_DELAY;
     }
 
     @Override
@@ -692,20 +1118,19 @@
                     Binder.getCallingUid());
             return;
         }
-        if (mActiveNetwork == null) {
-            pw.println("No active network");
-        } else {
-            pw.println("Active network: " +
-                    mActiveNetwork.getNetworkInfo().getTypeName());
-        }
         pw.println();
         for (NetworkStateTracker nst : mNetTrackers) {
+            if (nst.getNetworkInfo().isConnected()) {
+                pw.println("Active network: " + nst.getNetworkInfo().
+                        getTypeName());
+            }
             pw.println(nst.getNetworkInfo());
             pw.println(nst);
             pw.println();
         }
     }
 
+    // must be stateless - things change under us.
     private class MyHandler extends Handler {
         @Override
         public void handleMessage(Message msg) {
@@ -713,7 +1138,7 @@
             switch (msg.what) {
                 case NetworkStateTracker.EVENT_STATE_CHANGED:
                     info = (NetworkInfo) msg.obj;
-                    if (DBG) Log.v(TAG, "ConnectivityChange for " +
+                    if (DBG) Log.d(TAG, "ConnectivityChange for " +
                             info.getTypeName() + ": " +
                             info.getState() + "/" + info.getDetailedState());
 
@@ -748,7 +1173,6 @@
                     } else if (info.getState() == NetworkInfo.State.CONNECTED) {
                         handleConnect(info);
                     }
-                    handleConnectivityChange();
                     break;
 
                 case NetworkStateTracker.EVENT_SCAN_RESULTS_AVAILABLE:
@@ -761,7 +1185,7 @@
                             (Notification) msg.obj);
 
                 case NetworkStateTracker.EVENT_CONFIGURATION_CHANGED:
-                    handleConfigurationChange();
+                    handleDnsConfigurationChange();
                     break;
 
                 case NetworkStateTracker.EVENT_ROAMING_CHANGED:
@@ -771,6 +1195,15 @@
                 case NetworkStateTracker.EVENT_NETWORK_SUBTYPE_CHANGED:
                     // fill me in
                     break;
+                case NetworkStateTracker.EVENT_RESTORE_DEFAULT_NETWORK:
+                    for (NetworkStateTracker net : mNetTrackers) {
+                        NetworkInfo i = net.getNetworkInfo();
+                        if (i.isConnected() &&
+                                !mNetAttributes[i.getType()].isDefault()) {
+                            teardown(net);
+                        }
+                    }
+                    break;
             }
         }
     }
diff --git a/services/java/com/android/server/InputDevice.java b/services/java/com/android/server/InputDevice.java
index cb23c45..e1bce73 100644
--- a/services/java/com/android/server/InputDevice.java
+++ b/services/java/com/android/server/InputDevice.java
@@ -42,6 +42,10 @@
     long mKeyDownTime = 0;
     int mMetaKeysState = 0;
     
+    // For use by KeyInputQueue for keeping track of the current touch
+    // data in the old non-multi-touch protocol.
+    final int[] curTouchVals = new int[MotionEvent.NUM_SAMPLE_DATA * 2];
+    
     final MotionState mAbs = new MotionState(0, 0);
     final MotionState mRel = new MotionState(TRACKBALL_MOVEMENT_THRESHOLD,
             TRACKBALL_MOVEMENT_THRESHOLD);
@@ -410,7 +414,7 @@
                 
                 switch (orientation) {
                     case Surface.ROTATION_90: {
-                        final float temp = reportData[MotionEvent.SAMPLE_X];
+                        final float temp = reportData[j + MotionEvent.SAMPLE_X];
                         reportData[j + MotionEvent.SAMPLE_X] = reportData[j + MotionEvent.SAMPLE_Y];
                         reportData[j + MotionEvent.SAMPLE_Y] = w-temp;
                         break;
@@ -421,7 +425,7 @@
                         break;
                     }
                     case Surface.ROTATION_270: {
-                        final float temp = reportData[i + MotionEvent.SAMPLE_X];
+                        final float temp = reportData[j + MotionEvent.SAMPLE_X];
                         reportData[j + MotionEvent.SAMPLE_X] = h-reportData[j + MotionEvent.SAMPLE_Y];
                         reportData[j + MotionEvent.SAMPLE_Y] = temp;
                         break;
diff --git a/services/java/com/android/server/KeyInputQueue.java b/services/java/com/android/server/KeyInputQueue.java
index dc7d22b..7ca12f21 100644
--- a/services/java/com/android/server/KeyInputQueue.java
+++ b/services/java/com/android/server/KeyInputQueue.java
@@ -521,31 +521,29 @@
                             // Finger 1
                             if (ev.scancode == RawInputEvent.ABS_X) {
                                 di.mAbs.changed = true;
-                                di.mAbs.mNextData[MotionEvent.SAMPLE_X] = ev.value;
+                                di.curTouchVals[MotionEvent.SAMPLE_X] = ev.value;
                             } else if (ev.scancode == RawInputEvent.ABS_Y) {
                                 di.mAbs.changed = true;
-                                di.mAbs.mNextData[MotionEvent.SAMPLE_Y] = ev.value;
+                                di.curTouchVals[MotionEvent.SAMPLE_Y] = ev.value;
                             } else if (ev.scancode == RawInputEvent.ABS_PRESSURE) {
                                 di.mAbs.changed = true;
-                                di.mAbs.mNextData[MotionEvent.SAMPLE_PRESSURE] = ev.value;
-                                di.mAbs.mNextData[MotionEvent.NUM_SAMPLE_DATA
+                                di.curTouchVals[MotionEvent.SAMPLE_PRESSURE] = ev.value;
+                                di.curTouchVals[MotionEvent.NUM_SAMPLE_DATA
                                                  + MotionEvent.SAMPLE_PRESSURE] = ev.value;
                             } else if (ev.scancode == RawInputEvent.ABS_TOOL_WIDTH) {
                                 di.mAbs.changed = true;
-                                di.mAbs.mNextData[MotionEvent.SAMPLE_SIZE] = ev.value;
-                                di.mAbs.mNextData[MotionEvent.NUM_SAMPLE_DATA
+                                di.curTouchVals[MotionEvent.SAMPLE_SIZE] = ev.value;
+                                di.curTouchVals[MotionEvent.NUM_SAMPLE_DATA
                                                  + MotionEvent.SAMPLE_SIZE] = ev.value;
 
                             // Finger 2
                             } else if (ev.scancode == RawInputEvent.ABS_HAT0X) {
                                 di.mAbs.changed = true;
-                                di.mAbs.mNextData[(di.mAbs.mDown[0] ?
-                                        MotionEvent.NUM_SAMPLE_DATA : 0)
+                                di.curTouchVals[MotionEvent.NUM_SAMPLE_DATA 
                                          + MotionEvent.SAMPLE_X] = ev.value;
                             } else if (ev.scancode == RawInputEvent.ABS_HAT0Y) {
                                 di.mAbs.changed = true;
-                                di.mAbs.mNextData[(di.mAbs.mDown[0] ?
-                                        MotionEvent.NUM_SAMPLE_DATA : 0)
+                                di.curTouchVals[MotionEvent.NUM_SAMPLE_DATA
                                         + MotionEvent.SAMPLE_Y] = ev.value;
                             }
     
@@ -603,8 +601,21 @@
                                             |RawInputEvent.CLASS_TOUCHSCREEN_MT))
                                             == RawInputEvent.CLASS_TOUCHSCREEN) {
                                         ms.mNextNumPointers = 0;
-                                        if (ms.mDown[0]) ms.mNextNumPointers++;
-                                        if (ms.mDown[1]) ms.mNextNumPointers++;
+                                        if (ms.mDown[0]) {
+                                            System.arraycopy(di.curTouchVals, 0,
+                                                    ms.mNextData, 0,
+                                                    MotionEvent.NUM_SAMPLE_DATA);
+                                            ms.mNextNumPointers++;
+                                        }
+                                        if (ms.mDown[1]) {
+                                            System.arraycopy(di.curTouchVals,
+                                                    MotionEvent.NUM_SAMPLE_DATA,
+                                                    ms.mNextData,
+                                                    ms.mNextNumPointers
+                                                    * MotionEvent.NUM_SAMPLE_DATA,
+                                                    MotionEvent.NUM_SAMPLE_DATA);
+                                            ms.mNextNumPointers++;
+                                        }
                                     }
                                     
                                     boolean doMotion = !monitorVirtualKey(di,
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index e14f805..aac13b6 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -1138,25 +1138,57 @@
                     || p2 == null || p2.mExtras == null) {
                 return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
             }
-            return checkSignaturesLP(p1, p2);
+            return checkSignaturesLP(p1.mSignatures, p2.mSignatures);
         }
     }
 
-    int checkSignaturesLP(PackageParser.Package p1, PackageParser.Package p2) {
-        if (p1.mSignatures == null) {
-            return p2.mSignatures == null
+    public int checkUidSignatures(int uid1, int uid2) {
+        synchronized (mPackages) {
+            Signature[] s1;
+            Signature[] s2;
+            Object obj = mSettings.getUserIdLP(uid1);
+            if (obj != null) {
+                if (obj instanceof SharedUserSetting) {
+                    s1 = ((SharedUserSetting)obj).signatures.mSignatures;
+                } else if (obj instanceof PackageSetting) {
+                    s1 = ((PackageSetting)obj).signatures.mSignatures;
+                } else {
+                    return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
+                }
+            } else {
+                return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
+            }
+            obj = mSettings.getUserIdLP(uid2);
+            if (obj != null) {
+                if (obj instanceof SharedUserSetting) {
+                    s2 = ((SharedUserSetting)obj).signatures.mSignatures;
+                } else if (obj instanceof PackageSetting) {
+                    s2 = ((PackageSetting)obj).signatures.mSignatures;
+                } else {
+                    return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
+                }
+            } else {
+                return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
+            }
+            return checkSignaturesLP(s1, s2);
+        }
+    }
+
+    int checkSignaturesLP(Signature[] s1, Signature[] s2) {
+        if (s1 == null) {
+            return s2 == null
                     ? PackageManager.SIGNATURE_NEITHER_SIGNED
                     : PackageManager.SIGNATURE_FIRST_NOT_SIGNED;
         }
-        if (p2.mSignatures == null) {
+        if (s2 == null) {
             return PackageManager.SIGNATURE_SECOND_NOT_SIGNED;
         }
-        final int N1 = p1.mSignatures.length;
-        final int N2 = p2.mSignatures.length;
+        final int N1 = s1.length;
+        final int N2 = s2.length;
         for (int i=0; i<N1; i++) {
             boolean match = false;
             for (int j=0; j<N2; j++) {
-                if (p1.mSignatures[i].equals(p2.mSignatures[j])) {
+                if (s1[i].equals(s2[j])) {
                     match = true;
                     break;
                 }
@@ -2907,9 +2939,9 @@
                     allowed = true;
                 } else if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE
                         || p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
-                    allowed = (checkSignaturesLP(p.owner, pkg)
+                    allowed = (checkSignaturesLP(p.owner.mSignatures, pkg.mSignatures)
                                     == PackageManager.SIGNATURE_MATCH)
-                            || (checkSignaturesLP(mPlatformPackage, pkg)
+                            || (checkSignaturesLP(mPlatformPackage.mSignatures, pkg.mSignatures)
                                     == PackageManager.SIGNATURE_MATCH);
                     if (p.info.protectionLevel == PermissionInfo.PROTECTION_SIGNATURE_OR_SYSTEM) {
                         if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
@@ -3556,7 +3588,8 @@
         // First find the old package info and check signatures
         synchronized(mPackages) {
             oldPackage = mPackages.get(pkgName);
-            if(checkSignaturesLP(pkg, oldPackage) != PackageManager.SIGNATURE_MATCH) {
+            if(checkSignaturesLP(pkg.mSignatures, oldPackage.mSignatures)
+                    != PackageManager.SIGNATURE_MATCH) {
                 res.returnCode = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
                 return;
             }
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index c30386e..ad8e8921 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -84,6 +84,7 @@
 
         HardwareService hardware = null;
         PowerManagerService power = null;
+        BatteryService battery = null;
         IPackageManager pm = null;
         Context context = null;
         WindowManagerService wm = null;
@@ -132,7 +133,7 @@
             ActivityManagerService.installSystemProviders();
 
             Log.i(TAG, "Starting Battery Service.");
-            BatteryService battery = new BatteryService(context);
+            battery = new BatteryService(context);
             ServiceManager.addService("battery", battery);
 
             Log.i(TAG, "Starting Hardware Service.");
@@ -195,6 +196,7 @@
         InputMethodManagerService imm = null;
         AppWidgetService appWidget = null;
         NotificationManagerService notification = null;
+        WallpaperManagerService wallpaper = null;
 
         if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {
             try {
@@ -301,7 +303,8 @@
 
             try {
                 Log.i(TAG, "Starting Wallpaper Service");
-                ServiceManager.addService(Context.WALLPAPER_SERVICE, new WallpaperManagerService(context));
+                wallpaper = new WallpaperManagerService(context);
+                ServiceManager.addService(Context.WALLPAPER_SERVICE, wallpaper);
             } catch (Throwable e) {
                 Log.e(TAG, "Failure starting Wallpaper Service", e);
             }
@@ -380,6 +383,8 @@
         } catch (RemoteException e) {
         }
 
+        if (wallpaper != null) wallpaper.systemReady();
+        battery.systemReady();
         Watchdog.getInstance().start();
 
         Looper.loop();
diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java
index 9f2856c..7379b5d 100644
--- a/services/java/com/android/server/TelephonyRegistry.java
+++ b/services/java/com/android/server/TelephonyRegistry.java
@@ -88,6 +88,8 @@
 
     private String mDataConnectionApn = "";
 
+    private String[] mDataConnectionApnTypes = null;
+
     private String mDataConnectionInterfaceName = "";
 
     private Bundle mCellLocation = new Bundle();
@@ -337,7 +339,7 @@
     }
 
     public void notifyDataConnection(int state, boolean isDataConnectivityPossible,
-            String reason, String apn, String interfaceName) {
+            String reason, String apn, String[] apnTypes, String interfaceName) {
         if (!checkNotifyPermission("notifyDataConnection()" )) {
             return;
         }
@@ -346,6 +348,7 @@
             mDataConnectionPossible = isDataConnectivityPossible;
             mDataConnectionReason = reason;
             mDataConnectionApn = apn;
+            mDataConnectionApnTypes = apnTypes;
             mDataConnectionInterfaceName = interfaceName;
             for (int i = mRecords.size() - 1; i >= 0; i--) {
                 Record r = mRecords.get(i);
@@ -359,7 +362,7 @@
             }
         }
         broadcastDataConnectionStateChanged(state, isDataConnectivityPossible, reason, apn,
-                interfaceName);
+                apnTypes, interfaceName);
     }
 
     public void notifyDataConnectionFailed(String reason) {
@@ -517,8 +520,9 @@
         mContext.sendBroadcast(intent, android.Manifest.permission.READ_PHONE_STATE);
     }
 
-    private void broadcastDataConnectionStateChanged(int state, boolean isDataConnectivityPossible,
-            String reason, String apn, String interfaceName) {
+    private void broadcastDataConnectionStateChanged(int state,
+            boolean isDataConnectivityPossible,
+            String reason, String apn, String[] apnTypes, String interfaceName) {
         // Note: not reporting to the battery stats service here, because the
         // status bar takes care of that after taking into account all of the
         // required info.
@@ -531,6 +535,11 @@
             intent.putExtra(Phone.STATE_CHANGE_REASON_KEY, reason);
         }
         intent.putExtra(Phone.DATA_APN_KEY, apn);
+        String types = apnTypes[0];
+        for (int i = 1; i < apnTypes.length; i++) {
+            types = types+","+apnTypes[i];
+        }
+        intent.putExtra(Phone.DATA_APN_TYPES_KEY, types);
         intent.putExtra(Phone.DATA_IFACE_NAME_KEY, interfaceName);
         mContext.sendStickyBroadcast(intent);
     }
diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java
index 06565c7..9fe4eee 100644
--- a/services/java/com/android/server/WallpaperManagerService.java
+++ b/services/java/com/android/server/WallpaperManagerService.java
@@ -59,6 +59,7 @@
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
+import com.android.internal.service.wallpaper.ImageWallpaper;
 import com.android.internal.util.FastXmlSerializer;
 
 class WallpaperManagerService extends IWallpaperManager.Stub {
@@ -172,12 +173,29 @@
         mWallpaperObserver.stopWatching();
     }
     
+    public void systemReady() {
+        synchronized (mLock) {
+            try {
+                bindWallpaperComponentLocked(mWallpaperComponent);
+            } catch (RuntimeException e) {
+                Log.w(TAG, "Failure starting previous wallpaper", e);
+                try {
+                    bindWallpaperComponentLocked(null);
+                } catch (RuntimeException e2) {
+                    Log.w(TAG, "Failure starting default wallpaper", e2);
+                    clearWallpaperComponentLocked();
+                }
+            }
+        }
+    }
+    
     public void clearWallpaper() {
         synchronized (mLock) {
             File f = WALLPAPER_FILE;
             if (f.exists()) {
                 f.delete();
             }
+            bindWallpaperComponentLocked(null);
         }
     }
 
@@ -231,7 +249,7 @@
         synchronized (mLock) {
             ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name);
             if (pfd != null) {
-                clearWallpaperComponentLocked();
+                bindWallpaperComponentLocked(null);
                 saveSettingsLocked();
             }
             return pfd;
@@ -256,16 +274,45 @@
         synchronized (mLock) {
             final long ident = Binder.clearCallingIdentity();
             try {
-                ServiceInfo si = mContext.getPackageManager().getServiceInfo(name,
-                        PackageManager.GET_META_DATA | PackageManager.GET_PERMISSIONS);
-                if (!android.Manifest.permission.BIND_WALLPAPER.equals(si.permission)) {
-                    throw new SecurityException("Selected service does not require "
-                            + android.Manifest.permission.BIND_WALLPAPER
-                            + ": " + name);
+                bindWallpaperComponentLocked(name);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+    }
+    
+    void bindWallpaperComponentLocked(ComponentName name) {
+        // Has the component changed?
+        if (mWallpaperConnection != null) {
+            if (mWallpaperComponent == null) {
+                if (name == null) {
+                    // Still using default wallpaper.
+                    return;
                 }
-                
+            } else if (mWallpaperComponent.equals(name)) {
+                // Changing to same wallpaper.
+                return;
+            }
+        }
+        
+        try {
+            ComponentName realName = name;
+            if (realName == null) {
+                // The default component is our static image wallpaper.
+                realName = new ComponentName("android",
+                        ImageWallpaper.class.getName());
+            }
+            ServiceInfo si = mContext.getPackageManager().getServiceInfo(realName,
+                    PackageManager.GET_META_DATA | PackageManager.GET_PERMISSIONS);
+            if (!android.Manifest.permission.BIND_WALLPAPER.equals(si.permission)) {
+                throw new SecurityException("Selected service does not require "
+                        + android.Manifest.permission.BIND_WALLPAPER
+                        + ": " + realName);
+            }
+            
+            Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
+            if (name != null) {
                 // Make sure the selected service is actually a wallpaper service.
-                Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
                 List<ResolveInfo> ris = mContext.getPackageManager()
                         .queryIntentServices(intent, 0);
                 for (int i=0; i<ris.size(); i++) {
@@ -278,33 +325,31 @@
                 }
                 if (ris != null) {
                     throw new SecurityException("Selected service is not a wallpaper: "
-                            + name);
+                            + realName);
                 }
-                
-                // Bind the service!
-                WallpaperConnection newConn = new WallpaperConnection();
-                intent.setComponent(name);
-                if (!mContext.bindService(intent, newConn,
-                        Context.BIND_AUTO_CREATE)) {
-                    throw new IllegalArgumentException("Unable to bind service: "
-                            + name);
-                }
-                
-                clearWallpaperComponentLocked();
-                mWallpaperComponent = null;
-                mWallpaperConnection = newConn;
-                try {
-                    if (DEBUG) Log.v(TAG, "Adding window token: " + newConn.mToken);
-                    mIWindowManager.addWindowToken(newConn.mToken,
-                            WindowManager.LayoutParams.TYPE_WALLPAPER);
-                } catch (RemoteException e) {
-                }
-                
-            } catch (PackageManager.NameNotFoundException e) {
-                throw new IllegalArgumentException("Unknown component " + name);
-            } finally {
-                Binder.restoreCallingIdentity(ident);
             }
+            
+            // Bind the service!
+            WallpaperConnection newConn = new WallpaperConnection();
+            intent.setComponent(realName);
+            if (!mContext.bindService(intent, newConn,
+                    Context.BIND_AUTO_CREATE)) {
+                throw new IllegalArgumentException("Unable to bind service: "
+                        + name);
+            }
+            
+            clearWallpaperComponentLocked();
+            mWallpaperComponent = name;
+            mWallpaperConnection = newConn;
+            try {
+                if (DEBUG) Log.v(TAG, "Adding window token: " + newConn.mToken);
+                mIWindowManager.addWindowToken(newConn.mToken,
+                        WindowManager.LayoutParams.TYPE_WALLPAPER);
+            } catch (RemoteException e) {
+            }
+            
+        } catch (PackageManager.NameNotFoundException e) {
+            throw new IllegalArgumentException("Unknown component " + name);
         }
     }
     
@@ -327,7 +372,7 @@
             conn.mService.attach(conn, conn.mToken, mWidth, mHeight);
         } catch (RemoteException e) {
             Log.w(TAG, "Failed attaching wallpaper; clearing", e);
-            clearWallpaperComponentLocked();
+            bindWallpaperComponentLocked(null);
         }
     }
     
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 641f251..89b8ced 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -1237,6 +1237,10 @@
                 curWallpaperIndex--;
                 WindowState wallpaper = token.windows.get(curWallpaperIndex);
                 
+                if (visible) {
+                    updateWallpaperOffsetLocked(mWallpaperTarget, wallpaper, dw, dh);                        
+                }
+                
                 // First, make sure the client has the current visibility
                 // state.
                 if (wallpaper.mWallpaperVisible != visible) {
@@ -1250,10 +1254,6 @@
                     }
                 }
                 
-                if (visible) {
-                    updateWallpaperOffsetLocked(mWallpaperTarget, wallpaper, dw, dh);                        
-                }
-                
                 wallpaper.mAnimLayer = wallpaper.mLayer + mWallpaperAnimLayerAdjustment;
                 if (DEBUG_LAYERS) Log.v(TAG, "Wallpaper win " + wallpaper
                         + " anim layer: " + wallpaper.mAnimLayer);
@@ -1306,18 +1306,35 @@
 
     boolean updateWallpaperOffsetLocked(WindowState target,
             WindowState wallpaperWin, int dw, int dh) {
-        int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw;
-        int offset = availw > 0 ? -(int)(availw*target.mWallpaperX+.5f) : 0;
-        boolean changed = wallpaperWin.mXOffset != offset;
-        if (changed) {
-            wallpaperWin.mXOffset = offset;
+        boolean changed = false;
+        if (target.mWallpaperX >= 0) {
+            int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw;
+            int offset = availw > 0 ? -(int)(availw*target.mWallpaperX+.5f) : 0;
+            changed = wallpaperWin.mXOffset != offset;
+            if (changed) {
+                wallpaperWin.mXOffset = offset;
+            }
         }
-        int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh;
-        offset = availh > 0 ? -(int)(availh*target.mWallpaperY+.5f) : 0;
-        if (wallpaperWin.mYOffset != offset) {
-            changed = true;
-            wallpaperWin.mYOffset = offset;
+        if (target.mWallpaperY >= 0) {
+            int availh = wallpaperWin.mFrame.bottom-wallpaperWin.mFrame.top-dh;
+            int offset = availh > 0 ? -(int)(availh*target.mWallpaperY+.5f) : 0;
+            if (wallpaperWin.mYOffset != offset) {
+                changed = true;
+                wallpaperWin.mYOffset = offset;
+            }
         }
+        
+        if (wallpaperWin.mWallpaperX != target.mWallpaperX
+                || wallpaperWin.mWallpaperY != target.mWallpaperY) {
+            wallpaperWin.mWallpaperX = target.mWallpaperX;
+            wallpaperWin.mWallpaperY = target.mWallpaperY;
+            try {
+                wallpaperWin.mClient.dispatchWallpaperOffsets(
+                        wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY);
+            } catch (RemoteException e) {
+            }
+        }
+        
         return changed;
     }
     
@@ -5975,8 +5992,6 @@
         int mRequestedHeight;
         int mLastRequestedWidth;
         int mLastRequestedHeight;
-        int mXOffset;
-        int mYOffset;
         int mLayer;
         int mAnimLayer;
         int mLastLayer;
@@ -6061,8 +6076,14 @@
         boolean mHasLocalTransformation;
         final Transformation mTransformation = new Transformation();
 
-        float mWallpaperX = 0;
-        float mWallpaperY = 0;
+        // If a window showing a wallpaper: the requested offset for the
+        // wallpaper; if a wallpaper window: the currently applied offset.
+        float mWallpaperX = -1;
+        float mWallpaperY = -1;
+        
+        // Wallpaper windows: pixels offset based on above variables.
+        int mXOffset;
+        int mYOffset;
         
         // This is set after IWindowSession.relayout() has been called at
         // least once for the window.  It allows us to detect the situation
@@ -7181,7 +7202,7 @@
                 pw.print(prefix); pw.print("mHScale="); pw.print(mHScale);
                         pw.print(" mVScale="); pw.println(mVScale);
             }
-            if (mWallpaperX != 0 || mWallpaperY != 0) {
+            if (mWallpaperX != -1 || mWallpaperY != -1) {
                 pw.print(prefix); pw.print("mWallpaperX="); pw.print(mWallpaperX);
                         pw.print(" mWallpaperY="); pw.println(mWallpaperY);
             }
@@ -9468,6 +9489,7 @@
             pw.print("  mFocusedApp="); pw.println(mFocusedApp);
             pw.print("  mInputMethodTarget="); pw.println(mInputMethodTarget);
             pw.print("  mInputMethodWindow="); pw.println(mInputMethodWindow);
+            pw.print("  mWallpaperTarget="); pw.println(mWallpaperTarget);
             pw.print("  mInTouchMode="); pw.println(mInTouchMode);
             pw.print("  mSystemBooted="); pw.print(mSystemBooted);
                     pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled);
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 6907443..c59c9cc 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -4455,7 +4455,7 @@
     }
 
     final void appNotRespondingLocked(ProcessRecord app, HistoryRecord activity, 
-            final String annotation) {
+            HistoryRecord reportedActivity, final String annotation) {
         if (app.notResponding || app.crashing) {
             return;
         }
@@ -4483,8 +4483,13 @@
 
         StringBuilder info = mStringBuilder;
         info.setLength(0);
-        info.append("ANR (application not responding) in process: ");
+        info.append("ANR in process: ");
         info.append(app.processName);
+        if (reportedActivity != null && reportedActivity.app != null) {
+            info.append(" (last in ");
+            info.append(reportedActivity.app.processName);
+            info.append(")");
+        }
         if (annotation != null) {
             info.append("\nAnnotation: ");
             info.append(annotation);
@@ -4504,10 +4509,44 @@
         } else {
             // Dumping traces to a file so dump all active processes we know about
             synchronized (this) {
-                for (int i = mLRUProcesses.size() - 1 ; i >= 0 ; i--) {
+                // First, these are the most important processes.
+                final int[] imppids = new int[3];
+                int i=0;
+                imppids[0] = app.pid;
+                i++;
+                if (reportedActivity != null && reportedActivity.app != null
+                        && reportedActivity.app.thread != null
+                        && reportedActivity.app.pid != app.pid) {
+                    imppids[i] = reportedActivity.app.pid;
+                    i++;
+                }
+                imppids[i] = Process.myPid();
+                for (i=0; i<imppids.length && imppids[i] != 0; i++) {
+                    Process.sendSignal(imppids[i], Process.SIGNAL_QUIT);
+                    synchronized (this) {
+                        try {
+                            wait(200);
+                        } catch (InterruptedException e) {
+                        }
+                    }
+                }
+                for (i = mLRUProcesses.size() - 1 ; i >= 0 ; i--) {
                     ProcessRecord r = mLRUProcesses.get(i);
-                    if (r.thread != null) {
+                    boolean done = false;
+                    for (int j=0; j<imppids.length && imppids[j] != 0; j++) {
+                        if (imppids[j] == r.pid) {
+                            done = true;
+                            break;
+                        }
+                    }
+                    if (!done && r.thread != null) {
                         Process.sendSignal(r.pid, Process.SIGNAL_QUIT);
+                        synchronized (this) {
+                            try {
+                                wait(200);
+                            } catch (InterruptedException e) {
+                            }
+                        }
                     }
                 }
             }
@@ -4571,7 +4610,7 @@
                 if (!dir.exists()) {
                     fileReady = dir.mkdirs();
                     FileUtils.setPermissions(dir.getAbsolutePath(),
-                            FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IRWXO, -1, -1);
+                            FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IXOTH, -1, -1);
                 } else if (dir.isDirectory()) {
                     fileReady = true;
                 }
@@ -4581,6 +4620,18 @@
                 Log.i(TAG, "Removing old ANR trace file from " + tracesPath);
                 fileReady = f.delete();
             }
+            
+            if (removeExisting) {
+                try {
+                    f.createNewFile();
+                    FileUtils.setPermissions(f.getAbsolutePath(),
+                            FileUtils.S_IRWXU | FileUtils.S_IRWXG
+                            | FileUtils.S_IWOTH | FileUtils.S_IROTH, -1, -1);
+                    fileReady = true;
+                } catch (IOException e) {
+                    Log.w(TAG, "Unable to make ANR traces file", e);
+                }
+            }
         }
 
         return fileReady;
@@ -10639,7 +10690,7 @@
             }
             if (timeout != null && mLRUProcesses.contains(proc)) {
                 Log.w(TAG, "Timeout executing service: " + timeout);
-                appNotRespondingLocked(proc, null, "Executing service "
+                appNotRespondingLocked(proc, null, null, "Executing service "
                         + timeout.name);
             } else {
                 Message msg = mHandler.obtainMessage(SERVICE_TIMEOUT_MSG);
@@ -11434,7 +11485,8 @@
             }
             
             if (app != null) {
-                appNotRespondingLocked(app, null, "Broadcast of " + r.intent.toString());
+                appNotRespondingLocked(app, null, null,
+                        "Broadcast of " + r.intent.toString());
             }
 
             if (mPendingBroadcast == r) {
diff --git a/services/java/com/android/server/am/HistoryRecord.java b/services/java/com/android/server/am/HistoryRecord.java
index b3fc313..84ded22 100644
--- a/services/java/com/android/server/am/HistoryRecord.java
+++ b/services/java/com/android/server/am/HistoryRecord.java
@@ -470,7 +470,8 @@
                 }
                 
                 if (r.app.instrumentationClass == null) { 
-                    service.appNotRespondingLocked(r.app, r, "keyDispatchingTimedOut");
+                    service.appNotRespondingLocked(r.app, r, this,
+                            "keyDispatchingTimedOut");
                 } else {
                     Bundle info = new Bundle();
                     info.putString("shortMsg", "keyDispatchingTimedOut");
diff --git a/services/java/com/android/server/am/UsageStatsService.java b/services/java/com/android/server/am/UsageStatsService.java
old mode 100755
new mode 100644
index d458911..66868a3
--- a/services/java/com/android/server/am/UsageStatsService.java
+++ b/services/java/com/android/server/am/UsageStatsService.java
@@ -695,7 +695,14 @@
                 if (NC > 0) {
                     for (Map.Entry<String, TimeStats> ent : pus.mLaunchTimes.entrySet()) {
                         sb.append("A:");
-                        sb.append(ent.getKey());
+                        String activity = ent.getKey();
+                        if (activity.startsWith(pkgName)) {
+                            sb.append('*');
+                            sb.append(activity.substring(
+                                    pkgName.length(), activity.length()));
+                        } else {
+                            sb.append(activity);
+                        }
                         TimeStats times = ent.getValue();
                         sb.append(',');
                         sb.append(times.count);
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index a877c73..13713e5 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -26,8 +26,11 @@
 import android.text.Editable;
 import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
+import android.util.Log;
 import android.util.SparseIntArray;
 
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_IDP_STRING;
+
 import java.util.Locale;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -57,6 +60,9 @@
     public static final int TOA_International = 0x91;
     public static final int TOA_Unknown = 0x81;
 
+    static final String LOG_TAG = "PhoneNumberUtils";
+    private static final boolean DBG = false;
+
     /*
      * global-phone-number = ["+"] 1*( DIGIT / written-sep )
      * written-sep         = ("-"/".")
@@ -227,6 +233,9 @@
         }
     }
 
+    private static void log(String msg) {
+        Log.d(LOG_TAG, msg);
+    }
     /** index of the last character of the network portion
      *  (eg anything after is a post-dial string)
      */
@@ -741,6 +750,14 @@
         return true;
     }
 
+    private static boolean isNonSeparator(String address) {
+        for (int i = 0, count = address.length(); i < count; i++) {
+            if (!isNonSeparator(address.charAt(i))) {
+                return false;
+            }
+        }
+        return true;
+    }
     /**
      * Note: calls extractNetworkPortion(), so do not use for
      * SIM EF[ADN] style records
@@ -1229,4 +1246,261 @@
         KEYPAD_MAP.put('w', '9'); KEYPAD_MAP.put('x', '9'); KEYPAD_MAP.put('y', '9'); KEYPAD_MAP.put('z', '9');
         KEYPAD_MAP.put('W', '9'); KEYPAD_MAP.put('X', '9'); KEYPAD_MAP.put('Y', '9'); KEYPAD_MAP.put('Z', '9');
     }
+
+    //================ Plus Code formatting =========================
+    private static final char PLUS_SIGN_CHAR = '+';
+    private static final String PLUS_SIGN_STRING = "+";
+    private static final String NANP_IDP_STRING = "011";
+    private static final int NANP_LENGTH = 10;
+
+    /**
+     * This function checks if there is a plus sign (+) in the passed-in dialing number.
+     * If there is, it processes the plus sign based on the default telephone
+     * numbering plan of the system when the phone is activated and the current
+     * telephone numbering plan of the system that the phone is camped on.
+     * Currently, we only support the case that the default and current telephone
+     * numbering plans are North American Numbering Plan(NANP).
+     *
+     * The passed-in dialStr should only contain the valid format as described below,
+     * 1) the 1st character in the dialStr should be one of the really dialable
+     *    characters listed below
+     *    ISO-LATIN characters 0-9, *, # , +
+     * 2) the dialStr should already strip out the separator characters,
+     *    every character in the dialStr should be one of the non separator characters
+     *    listed below
+     *    ISO-LATIN characters 0-9, *, # , +, WILD, WAIT, PAUSE
+     *
+     * Otherwise, this function returns the dial string passed in
+     *
+     * This API is for CDMA only
+     *
+     * @hide TODO: pending API Council approval
+     */
+    public static String cdmaCheckAndProcessPlusCode(String dialStr) {
+        if (!TextUtils.isEmpty(dialStr)) {
+            if (isReallyDialable(dialStr.charAt(0)) &&
+                isNonSeparator(dialStr)) {
+                return cdmaCheckAndProcessPlusCodeByNumberFormat(dialStr,
+                        getFormatTypeForLocale(Locale.getDefault()));
+            }
+        }
+        return dialStr;
+    }
+
+    /**
+     * This function should be called from checkAndProcessPlusCode only
+     * And it is used for test purpose also.
+     *
+     * It checks the dial string by looping through the network portion,
+     * post dial portion 1, post dial porting 2, etc. If there is any
+     * plus sign, then process the plus sign.
+     * Currently, this function supports the plus sign conversion within NANP only.
+     * Specifically, it handles the plus sign in the following ways:
+     * 1)+NANP or +1NANP,remove +, e.g.
+     *   +8475797000 is converted to 8475797000,
+     *   +18475797000 is converted to 18475797000,
+     * 2)+non-NANP Numbers,replace + with the current NANP IDP, e.g,
+     *   +11875767800 is converted to 01111875767800
+     * 3)+NANP in post dial string(s), e.g.
+     *   8475797000;+8475231753 is converted to 8475797000;8475231753
+     *
+     * This function returns the original dial string if locale/numbering plan
+     * aren't supported.
+     *
+     * @hide
+     */
+    public static String cdmaCheckAndProcessPlusCodeByNumberFormat(String dialStr,int numFormat) {
+        String retStr = dialStr;
+
+        // Checks if the plus sign character is in the passed-in dial string
+        if (dialStr != null &&
+            dialStr.lastIndexOf(PLUS_SIGN_STRING) != -1) {
+
+            String postDialStr = null;
+            String tempDialStr = dialStr;
+
+            // Sets the retStr to null since the conversion will be performed below.
+            retStr = null;
+            if (DBG) log("checkAndProcessPlusCode,dialStr=" + dialStr);
+            // This routine is to process the plus sign in the dial string by loop through
+            // the network portion, post dial portion 1, post dial portion 2... etc. if
+            // applied
+            do {
+                String networkDialStr;
+
+                // Format the string based on the rules for the country the number is from
+                if (numFormat != FORMAT_NANP) {
+                    // TODO: to support NANP international conversion and
+                    // other telephone numbering plan
+                    // Currently the phone is ever used in non-NANP system
+                    // return the original dial string
+                    Log.e("checkAndProcessPlusCode:non-NANP not supported", dialStr);
+                    return dialStr;
+                } else {
+                    // For the case that the default and current telephone
+                    // numbering plans are NANP
+                    networkDialStr = extractNetworkPortion(tempDialStr);
+                    // Handles the conversion within NANP
+                    networkDialStr = processPlusCodeWithinNanp(networkDialStr);
+                }
+                // Concatenates the string that is converted from network portion
+                if (!TextUtils.isEmpty(networkDialStr)) {
+                    if (retStr == null) {
+                        retStr = networkDialStr;
+                    } else {
+                        retStr = retStr.concat(networkDialStr);
+                    }
+                } else {
+                    // This should never happen since we checked the if dialStr is null
+                    // and if it contains the plus sign in the begining of this function.
+                    // The plus sign is part of the network portion.
+                    Log.e("checkAndProcessPlusCode: null newDialStr", networkDialStr);
+                    return dialStr;
+                }
+                postDialStr = extractPostDialPortion(tempDialStr);
+                if (!TextUtils.isEmpty(postDialStr)) {
+                    int dialableIndex = findDialableIndexFromPostDialStr(postDialStr);
+
+                    // dialableIndex should always be greater than 0
+                    if (dialableIndex >= 1) {
+                        retStr = appendPwCharBackToOrigDialStr(dialableIndex,
+                                 retStr,postDialStr);
+                        // Skips the P/W character, extracts the dialable portion
+                        tempDialStr = postDialStr.substring(dialableIndex);
+                    } else {
+                        // Non-dialable character such as P/W should not be at the end of
+                        // the dial string after P/W processing in CdmaConnection.java
+                        // Set the postDialStr to "" to break out of the loop
+                        if (dialableIndex < 0) {
+                            postDialStr = "";
+                        }
+                        Log.e("wrong postDialStr=", postDialStr);
+                    }
+                }
+                if (DBG) log("checkAndProcessPlusCode,postDialStr=" + postDialStr);
+            } while (!TextUtils.isEmpty(postDialStr) && !TextUtils.isEmpty(tempDialStr));
+        }
+        return retStr;
+     }
+
+    // This function gets the default international dialing prefix
+    private static String getDefaultIdp( ) {
+        String ps = null;
+        SystemProperties.get(PROPERTY_IDP_STRING, ps);
+        if (TextUtils.isEmpty(ps)) {
+            ps = NANP_IDP_STRING;
+        }
+        return ps;
+    }
+
+    private static boolean isTwoToNine (char c) {
+        if (c >= '2' && c <= '9') {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * This function checks if the passed in string conforms to the NANP format
+     * i.e. NXX-NXX-XXXX, N is any digit 2-9 and X is any digit 0-9
+     */
+    private static boolean isNanp (String dialStr) {
+        boolean retVal = false;
+        if (dialStr != null) {
+            if (dialStr.length() == NANP_LENGTH) {
+                if (isTwoToNine(dialStr.charAt(0)) &&
+                    isTwoToNine(dialStr.charAt(3))) {
+                    retVal = true;
+                    for (int i=1; i<NANP_LENGTH; i++ ) {
+                        char c=dialStr.charAt(i);
+                        if (!PhoneNumberUtils.isISODigit(c)) {
+                            retVal = false;
+                            break;
+                        }
+                    }
+                }
+            }
+        } else {
+            Log.e("isNanp: null dialStr passed in", dialStr);
+        }
+        return retVal;
+    }
+
+   /**
+    * This function checks if the passed in string conforms to 1-NANP format
+    */
+    private static boolean isOneNanp(String dialStr) {
+        boolean retVal = false;
+        if (dialStr != null) {
+            String newDialStr = dialStr.substring(1);
+            if ((dialStr.charAt(0) == '1') && isNanp(newDialStr)) {
+                retVal = true;
+            }
+        } else {
+            Log.e("isOneNanp: null dialStr passed in", dialStr);
+        }
+        return retVal;
+    }
+
+    /**
+     * This function handles the plus code conversion within NANP CDMA network
+     * If the number format is
+     * 1)+NANP or +1NANP,remove +,
+     * 2)+non-NANP Numbers,replace + with the current IDP
+     */
+    private static String processPlusCodeWithinNanp(String networkDialStr) {
+        String retStr = networkDialStr;
+
+        if (DBG) log("processPlusCodeWithinNanp,networkDialStr=" + networkDialStr);
+        // If there is a plus sign at the beginning of the dial string,
+        // Convert the plus sign to the default IDP since it's an international number
+        if (networkDialStr != null &
+            networkDialStr.charAt(0) == PLUS_SIGN_CHAR &&
+            networkDialStr.length() > 1) {
+            String newStr = networkDialStr.substring(1);
+            if (isNanp(newStr) || isOneNanp(newStr)) {
+                // Remove the leading plus sign
+                retStr = newStr;
+             } else {
+                 String idpStr = getDefaultIdp();
+                 // Replaces the plus sign with the default IDP
+                 retStr = networkDialStr.replaceFirst("[+]", idpStr);
+            }
+        }
+        if (DBG) log("processPlusCodeWithinNanp,retStr=" + retStr);
+        return retStr;
+    }
+
+    // This function finds the index of the dialable character(s)
+    // in the post dial string
+    private static int findDialableIndexFromPostDialStr(String postDialStr) {
+        for (int index = 0;index < postDialStr.length();index++) {
+             char c = postDialStr.charAt(index);
+             if (isReallyDialable(c)) {
+                return index;
+             }
+        }
+        return -1;
+    }
+
+    // This function appends the non-diablable P/W character to the original
+    // dial string based on the dialable index passed in
+    private static String
+    appendPwCharBackToOrigDialStr(int dialableIndex,String origStr, String dialStr) {
+        String retStr;
+
+        // There is only 1 P/W character before the dialable characters
+        if (dialableIndex == 1) {
+            StringBuilder ret = new StringBuilder(origStr);
+            ret = ret.append(dialStr.charAt(0));
+            retStr = ret.toString();
+        } else {
+            // It means more than 1 P/W characters in the post dial string,
+            // appends to retStr
+            String nonDigitStr = dialStr.substring(0,dialableIndex);
+            retStr = origStr.concat(nonDigitStr);
+        }
+        return retStr;
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java b/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
index d6151c6..00d7c72 100644
--- a/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
+++ b/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
@@ -94,8 +94,11 @@
 
     public void notifyDataConnection(Phone sender, String reason) {
         try {
-            mRegistry.notifyDataConnection(convertDataState(sender.getDataConnectionState()),
-                    sender.isDataConnectivityPossible(), reason, sender.getActiveApn(),
+            mRegistry.notifyDataConnection(
+                    convertDataState(sender.getDataConnectionState()),
+                    sender.isDataConnectivityPossible(), reason,
+                    sender.getActiveApn(),
+                    sender.getActiveApnTypes(),
                     sender.getInterfaceName(null));
         } catch (RemoteException ex) {
             // system process is dead
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 865c6ca..6b42e6b 100644
--- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -32,7 +32,7 @@
     void notifyCallForwardingChanged(boolean cfi);
     void notifyDataActivity(int state);
     void notifyDataConnection(int state, boolean isDataConnectivityPossible,
-            String reason, String apn, String interfaceName);
+            String reason, String apn, in String[] apnTypes, String interfaceName);
     void notifyDataConnectionFailed(String reason);
     void notifyCellLocation(in Bundle cellLocation);
 }
diff --git a/telephony/java/com/android/internal/telephony/IccUtils.java b/telephony/java/com/android/internal/telephony/IccUtils.java
index 881ed2d..3e7094e 100644
--- a/telephony/java/com/android/internal/telephony/IccUtils.java
+++ b/telephony/java/com/android/internal/telephony/IccUtils.java
@@ -74,7 +74,7 @@
      * exactly as received"
      */
     public static int
-    bcdByteToInt(byte b) {
+    gsmBcdByteToInt(byte b) {
         int ret = 0;
 
         // treat out-of-range BCD values as 0
@@ -89,11 +89,14 @@
         return ret;
     }
 
-    /** Decodes BCD byte like {@link bcdByteToInt}, but the most significant BCD
-     *  digit is expected in the most significant nibble.
+    /**
+     * Decodes a CDMA style BCD byte like {@link gsmBcdByteToInt}, but
+     * opposite nibble format. The least significant BCD digit
+     * is in the least significant nibble and the most significant
+     * is in the most significant nibble.
      */
     public static int
-    beBcdByteToInt(byte b) {
+    cdmaBcdByteToInt(byte b) {
         int ret = 0;
 
         // treat out-of-range BCD values as 0
diff --git a/telephony/java/com/android/internal/telephony/Phone.java b/telephony/java/com/android/internal/telephony/Phone.java
index 86ea12b..622b47d 100644
--- a/telephony/java/com/android/internal/telephony/Phone.java
+++ b/telephony/java/com/android/internal/telephony/Phone.java
@@ -99,8 +99,9 @@
     static final String PHONE_NAME_KEY = "phoneName";
     static final String FAILURE_REASON_KEY = "reason";
     static final String STATE_CHANGE_REASON_KEY = "reason";
-    static final String DATA_APN_TYPE_KEY = "apnType";
+    static final String DATA_APN_TYPES_KEY = "apnType";
     static final String DATA_APN_KEY = "apn";
+
     static final String DATA_IFACE_NAME_KEY = "iface";
     static final String NETWORK_UNAVAILABLE_KEY = "networkUnvailable";
     static final String PHONE_IN_ECM_STATE = "phoneinECMState";
@@ -120,10 +121,16 @@
     static final String APN_TYPE_MMS = "mms";
     /** APN type for SUPL assisted GPS */
     static final String APN_TYPE_SUPL = "supl";
+    /** APN type for DUN traffic */
+    static final String APN_TYPE_DUN = "dun";
+    /** APN type for HiPri traffic */
+    static final String APN_TYPE_HIPRI = "hipri";
 
     // "Features" accessible through the connectivity manager
     static final String FEATURE_ENABLE_MMS = "enableMMS";
     static final String FEATURE_ENABLE_SUPL = "enableSUPL";
+    static final String FEATURE_ENABLE_DUN = "enableDUN";
+    static final String FEATURE_ENABLE_HIPRI = "enableHIPRI";
 
     /**
      * Return codes for <code>enableApnType()</code>
diff --git a/telephony/java/com/android/internal/telephony/RetryManager.java b/telephony/java/com/android/internal/telephony/RetryManager.java
index 242b2cd..385b191 100644
--- a/telephony/java/com/android/internal/telephony/RetryManager.java
+++ b/telephony/java/com/android/internal/telephony/RetryManager.java
@@ -41,7 +41,8 @@
  *</ul>
  *<p>
  * max_retries is the number of times that incrementRetryCount
- * maybe called before isRetryNeeded will return false.
+ * maybe called before isRetryNeeded will return false. if value
+ * is infinite then isRetryNeeded will always return true.
  *
  * default_randomizationTime will be used as the randomizationTime
  * for delay times which have no supplied randomizationTime. If
@@ -60,9 +61,13 @@
  * the 4..10 retries all using 3000 as the delay:
  * <ul><li><code>"max_retries=10, default_randomization=500, 1000, 2000, 3000"</code></ul>
  *
- * <li>4 retires with a 100ms default randomization value for the first 2 values and
- * the other two having specified values of 500ms:
+ * <li>4 retires with a 100 as the default randomization value for the first 2 values and
+ * the other two having specified values of 500:
  * <ul><li><code>"default_randomization=100, 1000, 2000, 4000:500, 5000:500"</code></ul>
+ *
+ * <li>Infinite number of retires with the first one at 1000, the second at 2000 all
+ * others will be at 3000.
+ * <ul><li><code>"max_retries=infinite,1000,2000,3000</code></ul>
  * </ul>
  *
  * {@hide}
@@ -181,9 +186,13 @@
                         if (!value.first) return false;
                         defaultRandomization = value.second;
                     } else if (TextUtils.equals(splitStr[0], "max_retries")) {
-                        value = parseNonNegativeInt(splitStr[0], splitStr[1]);
-                        if (!value.first) return false;
-                        mMaxRetryCount = value.second;
+                        if (TextUtils.equals("infinite",splitStr[1])) {
+                            mRetryForever = true;
+                        } else {
+                            value = parseNonNegativeInt(splitStr[0], splitStr[1]);
+                            if (!value.first) return false;
+                            mMaxRetryCount = value.second;
+                        }
                     } else {
                         Log.e(LOG_TAG, "Unrecognized configuration name value pair: "
                                         + strArray[i]);
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
old mode 100644
new mode 100755
index 69ef0e3..0c94e6a
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaConnection.java
@@ -818,15 +818,12 @@
         return c == PhoneNumberUtils.WAIT;
     }
 
-
-
-
     // This function is to find the next PAUSE character index if
     // multiple pauses in a row. Otherwise it finds the next non PAUSE or
     // non WAIT character index.
     private static int
     findNextPCharOrNonPOrNonWCharIndex(String phoneNumber, int currIndex) {
-        boolean wMatched = false;
+        boolean wMatched = isWait(phoneNumber.charAt(currIndex));
         int index = currIndex + 1;
         int length = phoneNumber.length();
         while (index < length) {
@@ -863,17 +860,17 @@
         // Append the PW char
         ret = (isPause(c)) ? PhoneNumberUtils.PAUSE : PhoneNumberUtils.WAIT;
 
-        // if there is a PAUSE in at the begining of PW character sequences, and this
-        // PW character sequences has more than 2 PAUSE and WAIT Characters,skip P, append W
-        if (isPause(c) &&  (nextNonPwCharIndex > (currPwIndex + 1))) {
+        // if there is a PAUSE in at the beginning of PW character sequences, and this
+        // PW character sequences has more than 2 PAUSE and WAIT Characters,skip PAUSE,
+        // append WAIT.
+        if (isPause(c) && (nextNonPwCharIndex > (currPwIndex + 2))) {
             ret = PhoneNumberUtils.WAIT;
         }
         return ret;
     }
 
-
     /**
-     * format orignal dial string
+     * format original dial string
      * 1) convert international dialing prefix "+" to
      *    string specified per region
      *
@@ -892,20 +889,10 @@
         StringBuilder ret = new StringBuilder();
         char c;
         int currIndex = 0;
+
         while (currIndex < length) {
             c = phoneNumber.charAt(currIndex);
-            if (PhoneNumberUtils.isDialable(c)) {
-                if (c == '+') {
-                    String ps = null;
-                    SystemProperties.get(TelephonyProperties.PROPERTY_IDP_STRING, ps);
-                    if (TextUtils.isEmpty(ps)) {
-                        ps = "011";
-                    }
-                    ret.append(ps);
-                } else {
-                    ret.append(c);
-                }
-            } else if (isPause(c) || isWait(c)) {
+            if (isPause(c) || isWait(c)) {
                 if (currIndex < length - 1) {
                     // if PW not at the end
                     int nextIndex = findNextPCharOrNonPOrNonWCharIndex(phoneNumber, currIndex);
@@ -913,8 +900,10 @@
                     if (nextIndex < length) {
                         char pC = findPOrWCharToAppend(phoneNumber, currIndex, nextIndex);
                         ret.append(pC);
-                        // If PW char is immediately followed by non-PW char
-                        if (nextIndex > (currIndex + 1)) {
+                        // If PW char sequence has more than 2 PW characters,
+                        // skip to the last character since the sequence already be
+                        // converted to WAIT character
+                        if (nextIndex > (currIndex + 2)) {
                             currIndex = nextIndex - 1;
                         }
                     } else if (nextIndex == length) {
@@ -927,7 +916,7 @@
             }
             currIndex++;
         }
-        return ret.toString();
+        return PhoneNumberUtils.cdmaCheckAndProcessPlusCode(ret.toString());
     }
 
     private void log(String msg) {
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index 753b5e7..b42cffd 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -1053,7 +1053,7 @@
             cdmaDataConnectionDetachedRegistrants.notifyRegistrants();
         }
 
-        if (hasCdmaDataConnectionChanged) {
+        if (hasCdmaDataConnectionChanged || hasNetworkTypeChanged) {
             phone.notifyDataConnection(null);
         }
 
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
index 65754fc..fefeb12 100644
--- a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
@@ -233,22 +233,22 @@
         public static TimeStamp fromByteArray(byte[] data) {
             TimeStamp ts = new TimeStamp();
             // C.S0015-B v2.0, 4.5.4: range is 1996-2095
-            int year = IccUtils.beBcdByteToInt(data[0]);
+            int year = IccUtils.cdmaBcdByteToInt(data[0]);
             if (year > 99 || year < 0) return null;
             ts.year = year >= 96 ? year + 1900 : year + 2000;
-            int month = IccUtils.beBcdByteToInt(data[1]);
+            int month = IccUtils.cdmaBcdByteToInt(data[1]);
             if (month < 1 || month > 12) return null;
             ts.month = month - 1;
-            int day = IccUtils.beBcdByteToInt(data[2]);
+            int day = IccUtils.cdmaBcdByteToInt(data[2]);
             if (day < 1 || day > 31) return null;
             ts.monthDay = day;
-            int hour = IccUtils.beBcdByteToInt(data[3]);
+            int hour = IccUtils.cdmaBcdByteToInt(data[3]);
             if (hour < 0 || hour > 23) return null;
             ts.hour = hour;
-            int minute = IccUtils.beBcdByteToInt(data[4]);
+            int minute = IccUtils.cdmaBcdByteToInt(data[4]);
             if (minute < 0 || minute > 59) return null;
             ts.minute = minute;
-            int second = IccUtils.beBcdByteToInt(data[5]);
+            int second = IccUtils.cdmaBcdByteToInt(data[5]);
             if (second < 0 || second > 59) return null;
             ts.second = second;
             return ts;
@@ -1153,7 +1153,7 @@
         if (paramBits >= EXPECTED_PARAM_SIZE) {
             paramBits -= EXPECTED_PARAM_SIZE;
             decodeSuccess = true;
-            bData.numberOfMessages = IccUtils.beBcdByteToInt((byte)inStream.read(8));
+            bData.numberOfMessages = IccUtils.cdmaBcdByteToInt((byte)inStream.read(8));
         }
         if ((! decodeSuccess) || (paramBits > 0)) {
             Log.d(LOG_TAG, "NUMBER_OF_MESSAGES decode " +
diff --git a/telephony/java/com/android/internal/telephony/gsm/ApnSetting.java b/telephony/java/com/android/internal/telephony/gsm/ApnSetting.java
index 3ca39de65..dc6f92d 100644
--- a/telephony/java/com/android/internal/telephony/gsm/ApnSetting.java
+++ b/telephony/java/com/android/internal/telephony/gsm/ApnSetting.java
@@ -72,7 +72,10 @@
 
     boolean canHandleType(String type) {
         for (String t : types) {
-            if (t.equals(type) || t.equals(Phone.APN_TYPE_ALL)) {
+            // DEFAULT handles all, and HIPRI is handled by DEFAULT
+            if (t.equals(type) || t.equals(Phone.APN_TYPE_ALL) ||
+                    (t.equals(Phone.APN_TYPE_DEFAULT) &&
+                    type.equals(Phone.APN_TYPE_HIPRI))) {
                 return true;
             }
         }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 8b3529f..bf60bfe 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -135,12 +135,16 @@
     /** Currently active PdpConnection */
     private PdpConnection mActivePdp;
 
+    private static int APN_INVALID_ID = -1;
     private static int APN_DEFAULT_ID = 0;
     private static int APN_MMS_ID = 1;
     private static int APN_SUPL_ID = 2;
-    private static int APN_NUM_TYPES = 3;
+    private static int APN_DUN_ID = 3;
+    private static int APN_HIPRI_ID = 4;
+    private static int APN_NUM_TYPES = 5;
 
     private boolean[] dataEnabled = new boolean[APN_NUM_TYPES];
+    private int enabledCount = 0;
 
     /** Is packet service restricted by network */
     private boolean mIsPsRestricted = false;
@@ -213,7 +217,6 @@
     GsmDataConnectionTracker(GSMPhone p) {
         super(p);
         mGsmPhone = p;
-
         p.mCM.registerForAvailable (this, EVENT_RADIO_AVAILABLE, null);
         p.mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
         p.mSIMRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null);
@@ -252,6 +255,9 @@
         // and 2) whether the RIL will setup the baseband to auto-PS attach.
         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(phone.getContext());
         dataEnabled[APN_DEFAULT_ID] = !sp.getBoolean(GSMPhone.DATA_DISABLED_ON_BOOT_KEY, false);
+        if (dataEnabled[APN_DEFAULT_ID]) {
+            enabledCount++;
+        }
         noAutoAttach = !dataEnabled[APN_DEFAULT_ID];
 
         if (!mRetryMgr.configure(SystemProperties.get("ro.gsm.data_retry_config"))) {
@@ -332,6 +338,22 @@
         return result;
     }
 
+    protected int apnTypeToId(String type) {
+        if (TextUtils.equals(type, Phone.APN_TYPE_DEFAULT)) {
+            return APN_DEFAULT_ID;
+        } else if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
+            return APN_MMS_ID;
+        } else if (TextUtils.equals(type, Phone.APN_TYPE_SUPL)) {
+            return APN_SUPL_ID;
+        } else if (TextUtils.equals(type, Phone.APN_TYPE_DUN)) {
+            return APN_DUN_ID;
+        } else if (TextUtils.equals(type, Phone.APN_TYPE_HIPRI)) {
+            return APN_HIPRI_ID;
+        } else {
+            return APN_INVALID_ID;
+        }
+    }
+
     /**
      * Ensure that we are connected to an APN of the specified type.
      * @param type the APN type (currently the only valid values
@@ -343,25 +365,15 @@
      * the APN has been established.
      */
     protected int enableApnType(String type) {
-        if (!TextUtils.equals(type, Phone.APN_TYPE_MMS) &&
-                !TextUtils.equals(type, Phone.APN_TYPE_SUPL)) {
+        int id = apnTypeToId(type);
+        if (id == APN_INVALID_ID) {
             return Phone.APN_REQUEST_FAILED;
         }
 
         // If already active, return
-        Log.d(LOG_TAG, "enableApnType("+type+")");
+        if(DBG) Log.d(LOG_TAG, "enableApnType("+type+"), isApnTypeActive = "
+                + isApnTypeActive(type) + " and state = " + state);
         if (isApnTypeActive(type)) {
-            setEnabled(type, true);
-            removeMessages(EVENT_RESTORE_DEFAULT_APN);
-            /**
-             * We're being asked to enable a non-default APN that's already in use.
-             * This means we should restart the timer that will automatically
-             * switch back to the default APN and disable the non-default APN
-             * when it expires.
-             */
-            sendMessageDelayed(
-                    obtainMessage(EVENT_RESTORE_DEFAULT_APN),
-                    getRestoreDefaultApnDelay());
             if (state == State.INITING) return Phone.APN_REQUEST_STARTED;
             else if (state == State.CONNECTED) return Phone.APN_ALREADY_ACTIVE;
         }
@@ -370,7 +382,7 @@
             return Phone.APN_TYPE_NOT_AVAILABLE;
         }
 
-        setEnabled(type, true);
+        setEnabled(id, true);
         mRequestedApnType = type;
         sendMessage(obtainMessage(EVENT_ENABLE_NEW_APN));
         return Phone.APN_REQUEST_STARTED;
@@ -385,31 +397,21 @@
      * @return
      */
     protected int disableApnType(String type) {
-        Log.d(LOG_TAG, "disableApnType("+type+")");
-        if ((TextUtils.equals(type, Phone.APN_TYPE_MMS) ||
-                TextUtils.equals(type, Phone.APN_TYPE_SUPL))
-                && isEnabled(type)) {
-            removeMessages(EVENT_RESTORE_DEFAULT_APN);
-            setEnabled(type, false);
+        if (DBG) Log.d(LOG_TAG, "disableApnType("+type+")");
+        int id = apnTypeToId(type);
+        if (id == APN_INVALID_ID) {
+            return Phone.APN_REQUEST_FAILED;
+        }
+        if (isEnabled(id)) {
+            setEnabled(id, false);
             if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
                 mRequestedApnType = Phone.APN_TYPE_DEFAULT;
                 if (dataEnabled[APN_DEFAULT_ID]) {
                     return Phone.APN_ALREADY_ACTIVE;
                 } else {
-                    Message msg = obtainMessage(EVENT_CLEAN_UP_CONNECTION);
-                    msg.arg1 = 1; // tearDown is true;
-                    msg.obj = Phone.REASON_DATA_DISABLED;
-                    sendMessage(msg);
                     return Phone.APN_REQUEST_STARTED;
                 }
             } else {
-                /*
-                 * Note that if default data is disabled, the following
-                 * has the effect of disabling the MMS APN, and then
-                 * ignoring the request to enable the default APN.
-                 * The net result is that data is completely disabled.
-                 */
-                sendMessage(obtainMessage(EVENT_RESTORE_DEFAULT_APN));
                 return Phone.APN_REQUEST_STARTED;
             }
         } else {
@@ -455,30 +457,30 @@
         return false;
     }
 
-    private boolean isEnabled(String apnType) {
-        if (TextUtils.equals(apnType, Phone.APN_TYPE_DEFAULT)) {
-            return dataEnabled[APN_DEFAULT_ID];
-        } else if (TextUtils.equals(apnType, Phone.APN_TYPE_MMS)) {
-            return dataEnabled[APN_MMS_ID];
-        } else if (TextUtils.equals(apnType, Phone.APN_TYPE_SUPL)) {
-            return dataEnabled[APN_SUPL_ID];
-        } else {
-            return false;
+    private boolean isEnabled(int id) {
+        if (id != APN_INVALID_ID) {
+            return dataEnabled[id];
         }
+        return false;
     }
 
-    private void setEnabled(String apnType, boolean enable) {
-        Log.d(LOG_TAG, "setEnabled(" + apnType + ", " + enable + ')');
-        if (TextUtils.equals(apnType, Phone.APN_TYPE_DEFAULT)) {
-            dataEnabled[APN_DEFAULT_ID] = enable;
-        } else if (TextUtils.equals(apnType, Phone.APN_TYPE_MMS)) {
-            dataEnabled[APN_MMS_ID] = enable;
-        } else if (TextUtils.equals(apnType, Phone.APN_TYPE_SUPL)) {
-            dataEnabled[APN_SUPL_ID] = enable;
+    private void setEnabled(int id, boolean enable) {
+        if (DBG) Log.d(LOG_TAG, "setEnabled(" + id + ", " + enable + ')');
+        if (dataEnabled[id] != enable) {
+            dataEnabled[id] = enable;
+
+            if (enable) {
+                enabledCount++;
+            } else {
+                enabledCount--;
+            }
+
+            if (enabledCount == 0) {
+                setPrivateDataEnabled(false);
+            } else if (enabledCount == 1) {
+                setPrivateDataEnabled(true);
+            }
         }
-        Log.d(LOG_TAG, "dataEnabled[DEFAULT_APN]=" + dataEnabled[APN_DEFAULT_ID] +
-                " dataEnabled[MMS_APN]=" + dataEnabled[APN_MMS_ID] +
-                " dataEnabled[SUPL_APN]=" + dataEnabled[APN_SUPL_ID]);
     }
 
     /**
@@ -493,30 +495,20 @@
      * @return {@code true} if the operation succeeded
      */
     public boolean setDataEnabled(boolean enable) {
-        boolean isEnabled = isEnabled(Phone.APN_TYPE_DEFAULT);
-        Log.d(LOG_TAG, "setDataEnabled("+enable+") isEnabled=" + isEnabled);
-        if (!isEnabled && enable) {
-            setEnabled(Phone.APN_TYPE_DEFAULT, true);
-            // trySetupData() will be a no-op if we are currently
-            // connected to the MMS APN
+        if (DBG) Log.d(LOG_TAG, "setDataEnabled("+enable+")");
+        setEnabled(APN_DEFAULT_ID, enable);
+        return true;
+    }
+
+    private void setPrivateDataEnabled(boolean enable) {
+        if (DBG) Log.d(LOG_TAG, "setPrivateDataEnabled("+enable+")");
+        if (enable) {
             sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
-            return true;
-        } else if (!enable) {
-            setEnabled(Phone.APN_TYPE_DEFAULT, false);
-            // Don't tear down if there is an active APN and it handles MMS or SUPL.
-            // TODO: This isn't very general.
-            if ((isApnTypeActive(Phone.APN_TYPE_MMS) && isEnabled(Phone.APN_TYPE_MMS)) ||
-                (isApnTypeActive(Phone.APN_TYPE_SUPL) && isEnabled(Phone.APN_TYPE_SUPL))) {
-                return false;
-            }
+        } else {
             Message msg = obtainMessage(EVENT_CLEAN_UP_CONNECTION);
             msg.arg1 = 1; // tearDown is true
             msg.obj = Phone.REASON_DATA_DISABLED;
             sendMessage(msg);
-            return true;
-        } else {
-            // isEnabled && enable
-            return true;
         }
     }
 
@@ -536,7 +528,7 @@
      * {@code true} otherwise.
      */
     public boolean getAnyDataEnabled() {
-        return dataEnabled[APN_DEFAULT_ID] || dataEnabled[APN_MMS_ID] || dataEnabled[APN_SUPL_ID];
+        return (enabledCount != 0);
     }
 
     /**
@@ -618,7 +610,7 @@
             }
 
             if (DBG) {
-                log ("Setup watingApns : " + apnListToString(waitingApns));
+                log ("Setup waitngApns : " + apnListToString(waitingApns));
             }
             return setupData(reason);
         } else {
@@ -629,6 +621,7 @@
                     " sim=" + mGsmPhone.mSIMRecords.getRecordsLoaded() +
                     " UMTS=" + mGsmPhone.mSST.isConcurrentVoiceAndData() +
                     " phoneState=" + phone.getState() +
+                    " isDataAllowed=" + isDataAllowed() +
                     " dataEnabled=" + getAnyDataEnabled() +
                     " roaming=" + roaming +
                     " dataOnRoamingEnable=" + getDataOnRoamingEnabled() +
@@ -1251,15 +1244,6 @@
         trySetupData(reason);
     }
 
-    protected void onRestoreDefaultApn() {
-        if (DBG) Log.d(LOG_TAG, "Restore default APN");
-        setEnabled(Phone.APN_TYPE_MMS, false);
-        mRequestedApnType = Phone.APN_TYPE_DEFAULT;
-        if (!isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
-            cleanUpConnection(true, Phone.REASON_RESTORE_DEFAULT_APN);
-        }
-    }
-
     protected void onRoamingOff() {
         trySetupData(Phone.REASON_ROAMING_OFF);
     }
@@ -1313,22 +1297,6 @@
 
         if (ar.exception == null) {
             // everything is setup
-
-            /*
-             * We may have switched away from the default PDP context
-             * in order to enable a "special" APN (e.g., for MMS
-             * traffic). Set a timer to switch back and/or disable the
-             * special APN, so that a negligient application doesn't
-             * permanently prevent data connectivity. What we are
-             * protecting against here is not malicious apps, but
-             * rather an app that inadvertantly fails to reset to the
-             * default APN, or that dies before doing so.
-             */
-            if (dataEnabled[APN_MMS_ID] || dataEnabled[APN_SUPL_ID]) {
-                removeMessages(EVENT_RESTORE_DEFAULT_APN);
-                sendMessageDelayed(obtainMessage(EVENT_RESTORE_DEFAULT_APN),
-                        getRestoreDefaultApnDelay());
-            }
             if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
                 SystemProperties.set("gsm.defaultpdpcontext.active", "true");
                         if (canSetPreferApn && preferredApn == null) {
@@ -1432,18 +1400,6 @@
         cleanUpConnection(tearDown, reason);
     }
 
-    private int getRestoreDefaultApnDelay() {
-        String restoreApnDelayStr = SystemProperties.get(APN_RESTORE_DELAY_PROP_NAME);
-
-        if (restoreApnDelayStr != null && restoreApnDelayStr.length() != 0) {
-            try {
-                return Integer.valueOf(restoreApnDelayStr);
-            } catch (NumberFormatException e) {
-            }
-        }
-        return RESTORE_DEFAULT_APN_DELAY;
-   }
-
     /**
      * Based on the sim operator numeric, create a list for all possible pdps
      * with all apns associated with that pdp
@@ -1568,10 +1524,7 @@
 
     private void startDelayedRetry(PdpConnection.FailCause cause, String reason) {
         notifyNoData(cause);
-        if (mRequestedApnType != Phone.APN_TYPE_DEFAULT) {
-            sendMessage(obtainMessage(EVENT_RESTORE_DEFAULT_APN));
-        }
-        else {
+        if (mRequestedApnType == Phone.APN_TYPE_DEFAULT) {
             reconnectAfterFail(cause, reason);
         }
     }
@@ -1626,7 +1579,7 @@
     }
 
     public void handleMessage (Message msg) {
-
+        if (DBG) Log.d(LOG_TAG,"GSMDataConnTrack handleMessage "+msg);
         switch (msg.what) {
             case EVENT_RECORDS_LOADED:
                 onRecordsLoaded();
@@ -1636,10 +1589,6 @@
                 onEnableNewApn();
                 break;
 
-            case EVENT_RESTORE_DEFAULT_APN:
-                onRestoreDefaultApn();
-                break;
-
             case EVENT_GPRS_DETACHED:
                 onGprsDetached();
                 break;
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
index f1207e4..93721ff 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
@@ -277,10 +277,12 @@
             }
 
             if (header != null) {
-                userData = new byte[header.length + textPart.length];
+                // Need 1 byte for UDHL
+                userData = new byte[header.length + textPart.length + 1];
 
-                System.arraycopy(header, 0, userData, 0, header.length);
-                System.arraycopy(textPart, 0, userData, header.length, textPart.length);
+                userData[0] = (byte)header.length;
+                System.arraycopy(header, 0, userData, 1, header.length);
+                System.arraycopy(textPart, 0, userData, header.length + 1, textPart.length);
             }
             else {
                 userData = textPart;
@@ -517,12 +519,12 @@
 
         long getSCTimestampMillis() {
             // TP-Service-Centre-Time-Stamp
-            int year = IccUtils.bcdByteToInt(pdu[cur++]);
-            int month = IccUtils.bcdByteToInt(pdu[cur++]);
-            int day = IccUtils.bcdByteToInt(pdu[cur++]);
-            int hour = IccUtils.bcdByteToInt(pdu[cur++]);
-            int minute = IccUtils.bcdByteToInt(pdu[cur++]);
-            int second = IccUtils.bcdByteToInt(pdu[cur++]);
+            int year = IccUtils.gsmBcdByteToInt(pdu[cur++]);
+            int month = IccUtils.gsmBcdByteToInt(pdu[cur++]);
+            int day = IccUtils.gsmBcdByteToInt(pdu[cur++]);
+            int hour = IccUtils.gsmBcdByteToInt(pdu[cur++]);
+            int minute = IccUtils.gsmBcdByteToInt(pdu[cur++]);
+            int second = IccUtils.gsmBcdByteToInt(pdu[cur++]);
 
             // For the timezone, the most significant bit of the
             // least signficant nibble is the sign byte
@@ -532,11 +534,9 @@
             byte tzByte = pdu[cur++];
 
             // Mask out sign bit.
-            int timezoneOffset = IccUtils
-                    .bcdByteToInt((byte) (tzByte & (~0x08)));
+            int timezoneOffset = IccUtils.gsmBcdByteToInt((byte) (tzByte & (~0x08)));
 
-            timezoneOffset = ((tzByte & 0x08) == 0) ? timezoneOffset
-                    : -timezoneOffset;
+            timezoneOffset = ((tzByte & 0x08) == 0) ? timezoneOffset : -timezoneOffset;
 
             Time time = new Time(Time.TIMEZONE_UTC);
 
diff --git a/test-runner/android/test/mock/MockPackageManager.java b/test-runner/android/test/mock/MockPackageManager.java
index 63a177e..4a50c5d 100644
--- a/test-runner/android/test/mock/MockPackageManager.java
+++ b/test-runner/android/test/mock/MockPackageManager.java
@@ -139,6 +139,11 @@
     }
 
     @Override
+    public int checkSignatures(int uid1, int uid2) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public String[] getPackagesForUid(int uid) {
         throw new UnsupportedOperationException();
     }
diff --git a/tests/CoreTests/com/android/internal/telephony/PhoneNumberUtilsTest.java b/tests/CoreTests/com/android/internal/telephony/PhoneNumberUtilsTest.java
index ff73b32..466b555 100644
--- a/tests/CoreTests/com/android/internal/telephony/PhoneNumberUtilsTest.java
+++ b/tests/CoreTests/com/android/internal/telephony/PhoneNumberUtilsTest.java
@@ -335,4 +335,73 @@
         assertEquals("(800) 222-3334",
                      PhoneNumberUtils.convertKeypadLettersToDigits("(800) ABC-DEFG"));
     }
+
+    @SmallTest
+    public void testCheckAndProcessPlusCode() {
+        assertEquals("8475797000",
+                PhoneNumberUtils.cdmaCheckAndProcessPlusCode("+8475797000"));
+        assertEquals("18475797000",
+                PhoneNumberUtils.cdmaCheckAndProcessPlusCode("+18475797000"));
+        assertEquals("0111234567",
+                PhoneNumberUtils.cdmaCheckAndProcessPlusCode("+1234567"));
+        assertEquals("01123456700000",
+                PhoneNumberUtils.cdmaCheckAndProcessPlusCode("+23456700000"));
+        assertEquals("01111875767800",
+                PhoneNumberUtils.cdmaCheckAndProcessPlusCode("+11875767800"));
+        assertEquals("8475797000,18475231753",
+                PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000,+18475231753"));
+        assertEquals("8475797000,18475231753",
+                PhoneNumberUtils.cdmaCheckAndProcessPlusCode("+8475797000,+18475231753"));
+        assertEquals("8475797000;8475231753",
+                PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000;+8475231753"));
+        assertEquals("8475797000,0111234567",
+                PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000,+1234567"));
+        assertEquals("847597000;01111875767000",
+                PhoneNumberUtils.cdmaCheckAndProcessPlusCode("847597000;+11875767000"));
+        assertEquals("8475797000,,8475231753",
+                PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000,,+8475231753"));
+        assertEquals("8475797000;,8475231753",
+                PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000;,+8475231753"));
+        assertEquals("8475797000,;18475231753",
+                PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000,;+18475231753"));
+        assertEquals("8475797000;,01111875767000",
+                PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000;,+11875767000"));
+        assertEquals("8475797000,;01111875767000",
+                PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000,;+11875767000"));
+        assertEquals("8475797000,,,01111875767000",
+                PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000,,,+11875767000"));
+        assertEquals("8475797000;,,01111875767000",
+                PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000;,,+11875767000"));
+        assertEquals("+;,8475797000",
+                PhoneNumberUtils.cdmaCheckAndProcessPlusCode("+;,8475797000"));
+        assertEquals("8475797000,",
+                PhoneNumberUtils.cdmaCheckAndProcessPlusCode("8475797000,"));
+        assertEquals("847+579-7000",
+                PhoneNumberUtils.cdmaCheckAndProcessPlusCode("847+579-7000"));
+        assertEquals(",8475797000",
+                PhoneNumberUtils.cdmaCheckAndProcessPlusCode(",8475797000"));
+        assertEquals(";;8475797000,,",
+                PhoneNumberUtils.cdmaCheckAndProcessPlusCode(";;8475797000,,"));
+        assertEquals("+this+is$weird;,+",
+                PhoneNumberUtils.cdmaCheckAndProcessPlusCode("+this+is$weird;,+"));
+        assertEquals("",
+                PhoneNumberUtils.cdmaCheckAndProcessPlusCode(""));
+        assertNull(PhoneNumberUtils.cdmaCheckAndProcessPlusCode(null));
+    }
+
+    @SmallTest
+    public void testCheckAndProcessPlusCodeByNumberFormat() {
+        assertEquals("+8475797000",
+                PhoneNumberUtils.cdmaCheckAndProcessPlusCodeByNumberFormat("+8475797000",
+                PhoneNumberUtils.FORMAT_JAPAN));
+        assertEquals("+0384756700",
+                PhoneNumberUtils.cdmaCheckAndProcessPlusCodeByNumberFormat("+0384756700",
+                PhoneNumberUtils.FORMAT_JAPAN));
+        assertEquals("+1234567",
+                PhoneNumberUtils.cdmaCheckAndProcessPlusCodeByNumberFormat("+1234567",
+                PhoneNumberUtils.FORMAT_UNKNOWN));
+        assertEquals("+23456700000",
+                PhoneNumberUtils.cdmaCheckAndProcessPlusCodeByNumberFormat("+23456700000",
+                PhoneNumberUtils.FORMAT_UNKNOWN));
+    }
 }
diff --git a/tests/CoreTests/com/android/internal/telephony/SimUtilsTest.java b/tests/CoreTests/com/android/internal/telephony/SimUtilsTest.java
index e733af9..6f25fd9 100644
--- a/tests/CoreTests/com/android/internal/telephony/SimUtilsTest.java
+++ b/tests/CoreTests/com/android/internal/telephony/SimUtilsTest.java
@@ -44,13 +44,22 @@
         assertEquals("890", IccUtils.bcdToString(data, 0, data.length));
 
         /*
-        * bcdByteToInt()
-        */
+         * gsmBcdByteToInt()
+         */
 
-        assertEquals(98, IccUtils.bcdByteToInt((byte) 0x89));
+        assertEquals(98, IccUtils.gsmBcdByteToInt((byte) 0x89));
 
         // Out of range is treated as 0
-        assertEquals(8, IccUtils.bcdByteToInt((byte) 0x8c));
+        assertEquals(8, IccUtils.gsmBcdByteToInt((byte) 0x8c));
+
+        /*
+         * cdmaBcdByteToInt()
+         */
+
+        assertEquals(89, IccUtils.cdmaBcdByteToInt((byte) 0x89));
+
+        // Out of range is treated as 0
+        assertEquals(80, IccUtils.gsmBcdByteToInt((byte) 0x8c));
 
         /*
          * adnStringFieldToString()
@@ -76,4 +85,3 @@
     }
 
 }
-
diff --git a/tests/CoreTests/com/android/internal/telephony/TelephonyUtilsTest.java b/tests/CoreTests/com/android/internal/telephony/TelephonyUtilsTest.java
index e4cf1e8..bf0c88b 100644
--- a/tests/CoreTests/com/android/internal/telephony/TelephonyUtilsTest.java
+++ b/tests/CoreTests/com/android/internal/telephony/TelephonyUtilsTest.java
@@ -123,6 +123,29 @@
     }
 
     /**
+     * Test infinite retires
+     */
+    @SmallTest
+    public void testRetryManageInfinite() throws Exception {
+        RetryManager rm = new RetryManager();
+
+        assertTrue(rm.configure("1000,2000,3000,max_retries=infinite"));
+        assertTrue(rm.isRetryNeeded());
+        assertEquals(1000, rm.getRetryTimer());
+        rm.increaseRetryCount();
+        assertTrue(rm.isRetryNeeded());
+        assertEquals(2000, rm.getRetryTimer());
+        rm.increaseRetryCount();
+        assertTrue(rm.isRetryNeeded());
+        // All others are 3000 and isRetryNeeded is always true
+        for (int i=0; i < 100; i++) {
+            assertEquals(3000, rm.getRetryTimer());
+            rm.increaseRetryCount();
+            assertTrue(rm.isRetryNeeded());
+        }
+    }
+
+    /**
      * Test string configuration using all options.
      */
     @SmallTest
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
index 7e80370..e060388 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
@@ -112,6 +112,11 @@
 
         mWebView.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL);
 
+        // Expose window.gc function to JavaScript. JSC build exposes
+        // this function by default, but V8 requires the flag to turn it on.
+        // WebView::setJsFlags is noop in JSC build.
+        mWebView.setJsFlags("--expose_gc");
+
         mHandler = new AsyncHandler();
 
         Intent intent = getIntent();
diff --git a/tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewCallbacks.java b/tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewCallbacks.java
index 89421e48..29000dd 100644
--- a/tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewCallbacks.java
+++ b/tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewCallbacks.java
@@ -19,8 +19,8 @@
 import android.app.Instrumentation;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.FlakyTest;
-import android.test.suitebuilder.annotation.MediumTest;
 
+// TODO: tests fail intermittently. Add back MediumTest annotation when fixed
 public class AutoCompleteTextViewCallbacks
         extends ActivityInstrumentationTestCase2<AutoCompleteTextViewSimple> {
 
@@ -32,7 +32,6 @@
 
     /** Test that the initial popup of the suggestions does not select anything.
      */
-    @MediumTest
     @FlakyTest(tolerance=3)
     public void testPopupNoSelection() throws Exception {
         AutoCompleteTextViewSimple theActivity = getActivity();
@@ -57,7 +56,6 @@
     }
 
     /** Test that arrow-down into the popup calls the onSelected callback. */
-    @MediumTest
     @FlakyTest(tolerance=3)
     public void testPopupEnterSelection() throws Exception {
         AutoCompleteTextViewSimple theActivity = getActivity();
@@ -95,7 +93,6 @@
     }
 
     /** Test that arrow-up out of the popup calls the onNothingSelected callback */
-    @MediumTest
     @FlakyTest(tolerance=3)
     public void testPopupLeaveSelection() {
         AutoCompleteTextViewSimple theActivity = getActivity();
diff --git a/tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewPopup.java b/tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewPopup.java
index 1e4cd20..c48c056 100644
--- a/tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewPopup.java
+++ b/tests/FrameworkTest/tests/src/android/widget/AutoCompleteTextViewPopup.java
@@ -20,10 +20,11 @@
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.FlakyTest;
 import android.test.suitebuilder.annotation.MediumTest;
-import android.util.Log;
 
 /**
  * A collection of tests on aspects of the AutoCompleteTextView's popup
+ *
+ * TODO: tests fail intermittently. Add back MediumTest annotation when fixed
  */
 public class AutoCompleteTextViewPopup
         extends ActivityInstrumentationTestCase2<AutoCompleteTextViewSimple> {
@@ -40,7 +41,6 @@
     }
 
     /** Test that we can move the selection and it responds as expected */
-    @MediumTest
     @FlakyTest(tolerance=3)
     public void testPopupSetListSelection() throws Throwable {
         AutoCompleteTextViewSimple theActivity = getActivity();
@@ -73,7 +73,6 @@
     }
 
     /** Test that we can look at the selection as we move around */
-    @MediumTest
     @FlakyTest(tolerance=3)
     public void testPopupGetListSelection() throws Throwable {
         AutoCompleteTextViewSimple theActivity = getActivity();
@@ -101,7 +100,6 @@
     }
 
     /** Test that we can clear the selection */
-    @MediumTest
     @FlakyTest(tolerance=3)
     public void testPopupClearListSelection() throws Throwable {
         AutoCompleteTextViewSimple theActivity = getActivity();
@@ -135,7 +133,6 @@
     }
 
     /** Make sure we handle an empty adapter properly */
-    @MediumTest
     @FlakyTest(tolerance=3)
     public void testPopupNavigateNoAdapter() throws Throwable {
         AutoCompleteTextViewSimple theActivity = getActivity();
@@ -170,7 +167,6 @@
     }
 
     /** Test the show/hide behavior of the drop-down. */
-    @MediumTest
     @FlakyTest(tolerance=3)
     public void testPopupShow() throws Throwable {
         AutoCompleteTextViewSimple theActivity = getActivity();
diff --git a/tests/backup/AndroidManifest.xml b/tests/backup/AndroidManifest.xml
index 3778742..d992627 100644
--- a/tests/backup/AndroidManifest.xml
+++ b/tests/backup/AndroidManifest.xml
@@ -1,5 +1,6 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
         package="com.android.backuptest">
+    <uses-permission android:name="android.permission.BACKUP_DATA" />
     <application android:backupAgent="BackupTestAgent">
         <activity android:name="BackupTestActivity" android:label="_BackupTest">
             <intent-filter>
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 41ee88b..9d2ed10 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -475,10 +475,8 @@
                     }
                 } else {
                     // this group doesn't exist (a file that's only in the overlay)
-                    fprintf(stderr, "aapt: error: "
-                            "*** Resource file '%s' exists only in an overlay\n",
-                            overlaySet->keyAt(overlayIndex).string());
-                    return false;
+                    baseSet->add(overlaySet->keyAt(overlayIndex),
+                            overlaySet->valueAt(overlayIndex));
                 }
             }
             // this overlay didn't have resources for this type
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 8dbc12e..95a2384 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -663,6 +663,7 @@
     const String16 public16("public");
     const String16 public_padding16("public-padding");
     const String16 private_symbols16("private-symbols");
+    const String16 add_resource16("add-resource");
     const String16 skip16("skip");
     const String16 eat_comment16("eat-comment");
 
@@ -960,6 +961,36 @@
                 }
                 continue;
 
+            } else if (strcmp16(block.getElementName(&len), add_resource16.string()) == 0) {
+                SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
+            
+                String16 typeName;
+                ssize_t typeIdx = block.indexOfAttribute(NULL, "type");
+                if (typeIdx < 0) {
+                    srcPos.error("A 'type' attribute is required for <add-resource>\n");
+                    hasErrors = localHasErrors = true;
+                }
+                typeName = String16(block.getAttributeStringValue(typeIdx, &len));
+
+                String16 name;
+                ssize_t nameIdx = block.indexOfAttribute(NULL, "name");
+                if (nameIdx < 0) {
+                    srcPos.error("A 'name' attribute is required for <add-resource>\n");
+                    hasErrors = localHasErrors = true;
+                }
+                name = String16(block.getAttributeStringValue(nameIdx, &len));
+
+                outTable->canAddEntry(srcPos, myPackage, typeName, name);
+
+                while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
+                    if (code == ResXMLTree::END_TAG) {
+                        if (strcmp16(block.getElementName(&len), private_symbols16.string()) == 0) {
+                            break;
+                        }
+                    }
+                }
+                continue;
+                
             } else if (strcmp16(block.getElementName(&len), declare_styleable16.string()) == 0) {
                 SourcePos srcPos(in->getPrintableSource(), block.getLineNumber());
                                 
@@ -1557,9 +1588,21 @@
     }
 #endif
     if (overlay && !hasBagOrEntry(package, type, name)) {
-        sourcePos.error("Can't add new bags in an overlay.  See '%s'\n",
-                        String8(name).string());
-        return UNKNOWN_ERROR;
+        bool canAdd = false;
+        sp<Package> p = mPackages.valueFor(package);
+        if (p != NULL) {
+            sp<Type> t = p->getTypes().valueFor(type);
+            if (t != NULL) {
+                if (t->getCanAddEntries().indexOf(name) >= 0) {
+                    canAdd = true;
+                }
+            }
+        }
+        if (!canAdd) {
+            sourcePos.error("Resource does not already exist in overlay at '%s'; use <add-resource> to add.\n",
+                            String8(name).string());
+            return UNKNOWN_ERROR;
+        }
     }
     sp<Entry> e = getEntry(package, type, name, sourcePos, overlay, params);
     if (e == NULL) {
@@ -1724,6 +1767,15 @@
     return false;
 }
 
+void ResourceTable::canAddEntry(const SourcePos& pos,
+        const String16& package, const String16& type, const String16& name)
+{
+    sp<Type> t = getType(package, type, pos);
+    if (t != NULL) {
+        t->canAddEntry(name);
+    }
+}
+
 size_t ResourceTable::size() const {
     return mPackages.size();
 }
@@ -3215,6 +3267,11 @@
     return NO_ERROR;
 }
 
+void ResourceTable::Type::canAddEntry(const String16& name)
+{
+    mCanAddEntries.add(name);
+}
+
 sp<ResourceTable::Entry> ResourceTable::Type::getEntry(const String16& entry,
                                                        const SourcePos& sourcePos,
                                                        const ResTable_config* config,
@@ -3224,9 +3281,10 @@
     int pos = -1;
     sp<ConfigList> c = mConfigs.valueFor(entry);
     if (c == NULL) {
-        if (overlay == true) {
-            sourcePos.error("Resource %s appears in overlay but not"
-                            " in the base package.\n", String8(entry).string());
+        if (overlay == true && mCanAddEntries.indexOf(entry) < 0) {
+            sourcePos.error("Resource at %s appears in overlay but not"
+                            " in the base package; use <add-resource> to add.\n",
+                            String8(entry).string());
             return NULL;
         }
         c = new ConfigList(entry, sourcePos);
diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h
index ec4331a..caa01b3 100644
--- a/tools/aapt/ResourceTable.h
+++ b/tools/aapt/ResourceTable.h
@@ -132,6 +132,9 @@
                            const String16& name,
                            const String16& comment);
     
+    void canAddEntry(const SourcePos& pos,
+        const String16& package, const String16& type, const String16& name);
+        
     size_t size() const;
     size_t numLocalResources() const;
     bool hasResources() const;
@@ -413,7 +416,9 @@
         status_t addPublic(const SourcePos& pos,
                            const String16& name,
                            const uint32_t ident);
-
+                           
+        void canAddEntry(const String16& name);
+        
         String16 getName() const { return mName; }
         sp<Entry> getEntry(const String16& entry,
                            const SourcePos& pos,
@@ -435,6 +440,8 @@
         const DefaultKeyedVector<String16, sp<ConfigList> >& getConfigs() const { return mConfigs; }
         const Vector<sp<ConfigList> >& getOrderedConfigs() const { return mOrderedConfigs; }
 
+        const SortedVector<String16>& getCanAddEntries() const { return mCanAddEntries; }
+        
         const SourcePos& getPos() const { return mPos; }
     private:
         String16 mName;
@@ -443,6 +450,7 @@
         SortedVector<ConfigDescription> mUniqueConfigs;
         DefaultKeyedVector<String16, sp<ConfigList> > mConfigs;
         Vector<sp<ConfigList> > mOrderedConfigs;
+        SortedVector<String16> mCanAddEntries;
         int32_t mPublicIndex;
         int32_t mIndex;
         SourcePos mPos;
diff --git a/tools/layoutlib/bridge/src/android/webkit/WebView.java b/tools/layoutlib/bridge/src/android/webkit/WebView.java
index 42e4dfa..3b66188 100644
--- a/tools/layoutlib/bridge/src/android/webkit/WebView.java
+++ b/tools/layoutlib/bridge/src/android/webkit/WebView.java
@@ -240,13 +240,6 @@
         return null;
     }
 
-    public static synchronized PluginList getPluginList() {
-        return null;
-    }
-
-    public void refreshPlugins(boolean reloadOpenPages) {
-    }
-
     public View getZoomControls() {
         return null;
     }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index 8e7d48f..8d44ac08 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -1047,6 +1047,11 @@
             // pass for now.
         }
 
+        @SuppressWarnings("unused")
+        public void dispatchWallpaperOffsets(float x, float y) {
+            // pass for now.
+        }
+
         public IBinder asBinder() {
             // pass for now.
             return null;
diff --git a/tools/preload/20090811.compiled b/tools/preload/20090811.compiled
new file mode 100644
index 0000000..dd61487
--- /dev/null
+++ b/tools/preload/20090811.compiled
Binary files differ
diff --git a/tools/preload/ClassRank.java b/tools/preload/ClassRank.java
index 3699b89..c562d5c 100644
--- a/tools/preload/ClassRank.java
+++ b/tools/preload/ClassRank.java
@@ -26,7 +26,7 @@
      * Increase this number to add more weight to classes which were loaded
      * earlier.
      */
-    static final int SEQUENCE_WEIGHT = 500; // 5 ms
+    static final int SEQUENCE_WEIGHT = 500; // 0.5ms
 
     static final int BUCKET_SIZE = 5;
 
diff --git a/tools/preload/LoadedClass.java b/tools/preload/LoadedClass.java
index 5782807..9ef17f5 100644
--- a/tools/preload/LoadedClass.java
+++ b/tools/preload/LoadedClass.java
@@ -15,10 +15,7 @@
  */
 
 import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
 
 /**
  * A loaded class.
@@ -54,7 +51,7 @@
     }
 
     void measureMemoryUsage() {
-        this.memoryUsage = MemoryUsage.forClass(name);        
+//        this.memoryUsage = MemoryUsage.forClass(name);
     }
 
     int mlt = -1;
@@ -102,31 +99,20 @@
         }
     }
 
-    /**
-     * Counts loads by apps.
-     */
-    int appLoads() {
-        return operationsByApps(loads);
+    /** Returns names of apps that loaded this class. */
+    Set<String> applicationNames() {
+        Set<String> appNames = new HashSet<String>();
+        addProcessNames(loads, appNames);
+        addProcessNames(initializations, appNames);
+        return appNames;
     }
 
-    /**
-     * Counts inits by apps.
-     */
-    int appInits() {
-        return operationsByApps(initializations);
-    }
-
-    /**
-     * Counts number of app operations in the given list.
-     */
-    private static int operationsByApps(List<Operation> operations) {
-        int byApps = 0;
-        for (Operation operation : operations) {
+    private void addProcessNames(List<Operation> ops, Set<String> appNames) {
+        for (Operation operation : ops) {
             if (operation.process.isApplication()) {
-                byApps++;
+                appNames.add(operation.process.name);
             }
         }
-        return byApps;
     }
 
     public int compareTo(LoadedClass o) {
@@ -160,4 +146,8 @@
 
         return false;
     }
+
+    public boolean isPreloadable() {
+        return systemClass && Policy.isPreloadableClass(name);
+    }
 }
diff --git a/tools/preload/Policy.java b/tools/preload/Policy.java
index 554966b..ade889e3 100644
--- a/tools/preload/Policy.java
+++ b/tools/preload/Policy.java
@@ -24,47 +24,32 @@
 public class Policy {
     
     /**
+     * No constructor - use static methods only
+     */
+    private Policy() {}
+
+    /**
      * This location (in the build system) of the preloaded-classes file.
      */
-    private static final String PRELOADED_CLASS_FILE = "frameworks/base/preloaded-classes";
-    
+    private static final String PRELOADED_CLASS_FILE
+            = "frameworks/base/preloaded-classes";
+
     /**
-     * The internal process name of the system process.  Note, this also shows up as
-     * "system_process", e.g. in ddms.
-     */
-    private static final String SYSTEM_SERVER_PROCESS_NAME = "system_server";
-
-    /** 
-     * Names of non-application processes - these will not be checked for preloaded classes.
-     * 
-     * TODO: Replace this hardcoded list with a walk up the parent chain looking for zygote.
-     */
-    private static final Set<String> NOT_FROM_ZYGOTE = new HashSet<String>(Arrays.asList(
-            "zygote",
-            "dexopt",
-            "unknown",
-            SYSTEM_SERVER_PROCESS_NAME,
-            "com.android.development",
-            "app_process" // am & other shell commands
-    ));
-
-    /** 
-     * Long running services.  These are restricted in their contribution to the preloader
-     * because their launch time is less critical.
+     * Long running services. These are restricted in their contribution to the 
+     * preloader because their launch time is less critical.
      */
     private static final Set<String> SERVICES = new HashSet<String>(Arrays.asList(
-            SYSTEM_SERVER_PROCESS_NAME,
-            "com.android.acore",
-         // Commented out to make sure DefaultTimeZones gets preloaded.
-         // "com.android.phone",
+            "system_server",
             "com.google.process.content",
-            "android.process.media"
+            "android.process.media",
+            "com.google.process.gapps"
     ));
 
     /**
      * Classes which we shouldn't load from the Zygote.
      */
-    private static final Set<String> EXCLUDED_CLASSES = new HashSet<String>(Arrays.asList(
+    private static final Set<String> EXCLUDED_CLASSES
+            = new HashSet<String>(Arrays.asList(
         // Binders
         "android.app.AlarmManager",
         "android.app.SearchManager",
@@ -75,15 +60,9 @@
         "android.os.AsyncTask",
         "android.pim.ContactsAsyncHelper",
         "java.lang.ProcessManager"
-        
     ));
 
     /**
-     * No constructor - use static methods only
-     */
-    private Policy() {}
-    
-    /**
      * Returns the path/file name of the preloaded classes file that will be written 
      * by WritePreloadedClassFile.
      */
@@ -92,13 +71,6 @@
     }
     
     /**
-     * Reports if a given process name was created from zygote
-     */
-    public static boolean isFromZygote(String processName) {
-        return !NOT_FROM_ZYGOTE.contains(processName);
-    }
-    
-    /**
      * Reports if the given process name is a "long running" process or service
      */
     public static boolean isService(String processName) {
diff --git a/tools/preload/PrintCsv.java b/tools/preload/PrintCsv.java
index 9f2a318..62f4271 100644
--- a/tools/preload/PrintCsv.java
+++ b/tools/preload/PrintCsv.java
@@ -18,6 +18,9 @@
 import java.io.FileInputStream;
 import java.io.ObjectInputStream;
 import java.io.BufferedInputStream;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.TreeSet;
 
 /**
  * Prints raw information in CSV format.
@@ -37,13 +40,14 @@
                 + ",Preloaded"
                 + ",Median Load Time (us)"
                 + ",Median Init Time (us)"
+                + ",Process Names"
                 + ",Load Count"
-                + ",Init Count"
-                + ",Managed Heap (B)"
-                + ",Native Heap (B)"
-                + ",Managed Pages (kB)"
-                + ",Native Pages (kB)"
-                + ",Other Pages (kB)");
+                + ",Init Count");
+//                + ",Managed Heap (B)"
+//                + ",Native Heap (B)"
+//                + ",Managed Pages (kB)"
+//                + ",Native Pages (kB)"
+//                + ",Other Pages (kB)");
 
         MemoryUsage baseline = root.baseline;
 
@@ -60,10 +64,23 @@
             System.out.print(',');
             System.out.print(loadedClass.medianInitTimeMicros());
             System.out.print(',');
+            System.out.print('"');
+
+            Set<String> procNames = new TreeSet<String>();
+            for (Operation op : loadedClass.loads)
+                procNames.add(op.process.name);
+            for (Operation op : loadedClass.initializations)
+                procNames.add(op.process.name);
+            for (String name : procNames) {
+                System.out.print(name + "\n");
+            }
+            
+            System.out.print('"');
+            System.out.print(',');
             System.out.print(loadedClass.loads.size());
             System.out.print(',');
             System.out.print(loadedClass.initializations.size());
-
+/*
             if (loadedClass.memoryUsage.isAvailable()) {
                 MemoryUsage subtracted
                         = loadedClass.memoryUsage.subtract(baseline);
@@ -82,7 +99,7 @@
             } else {
                 System.out.print(",n/a,n/a,n/a,n/a,n/a");
             }
-
+*/
             System.out.println();
         }
     }
diff --git a/tools/preload/Proc.java b/tools/preload/Proc.java
index 22697f8..66e04dc 100644
--- a/tools/preload/Proc.java
+++ b/tools/preload/Proc.java
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-import java.util.Set;
-import java.util.HashSet;
 import java.util.Arrays;
 import java.util.List;
 import java.util.ArrayList;
@@ -23,7 +21,6 @@
 import java.util.Map;
 import java.util.HashMap;
 import java.util.Collections;
-import java.util.TreeSet;
 import java.io.Serializable;
 
 /**
@@ -38,11 +35,6 @@
      */
     static final int PERCENTAGE_TO_PRELOAD = 75;
 
-    /**
-     * Maximum number of classes to preload for a given process.
-     */
-    static final int MAX_TO_PRELOAD = 100;
-
     /** Parent process. */
     final Proc parent;
 
@@ -97,11 +89,9 @@
 
     /**
      * Returns a list of classes which should be preloaded.
-     * 
-     * @param takeAllClasses forces all classes to be taken (irrespective of ranking)
      */
-    List<LoadedClass> highestRankedClasses(boolean takeAllClasses) {
-        if (!isApplication()) {
+    List<LoadedClass> highestRankedClasses() {
+        if (!isApplication() || Policy.isService(this.name)) {
             return Collections.emptyList();
         }
 
@@ -114,25 +104,13 @@
         int timeToSave = totalTimeMicros() * percentageToPreload() / 100;
         int timeSaved = 0;
 
-        boolean service = Policy.isService(this.name);
-
+        int count = 0;
         List<LoadedClass> highest = new ArrayList<LoadedClass>();
         for (Operation operation : ranked) {
-            
-            // These are actual ranking decisions, which can be overridden
-            if (!takeAllClasses) {
-                if (highest.size() >= MAX_TO_PRELOAD) {
-                    System.out.println(name + " got " 
-                            + (timeSaved * 100 / timeToSave) + "% through");
-                    break;
-                }
-    
-                if (timeSaved >= timeToSave) {
-                    break;
-                }
+            if (timeSaved >= timeToSave || count++ > 100) {
+                break;
             }
 
-            // The remaining rules apply even to wired-down processes
             if (!Policy.isPreloadableClass(operation.loadedClass.name)) {
                 continue;
             }
@@ -140,13 +118,8 @@
             if (!operation.loadedClass.systemClass) {
                 continue;
             }
-
-            // Only load java.* class for services.
-            if (!service || operation.loadedClass.name.startsWith("java.")) {
-                highest.add(operation.loadedClass);
-            }
-
-            // For services, still count the time even if it's not in java.* 
+    
+            highest.add(operation.loadedClass);
             timeSaved += operation.medianExclusiveTimeMicros();
         }
 
@@ -166,11 +139,13 @@
 
     /** 
      * Returns true if this process is an app.
-     *      
-     * TODO: Replace the hardcoded list with a walk up the parent chain looking for zygote.
      */
     public boolean isApplication() {
-        return Policy.isFromZygote(name);
+        if (name.equals("com.android.development")) {
+            return false;
+        }
+
+        return parent != null && parent.name.equals("zygote");
     }
 
     /**
diff --git a/tools/preload/WritePreloadedClassFile.java b/tools/preload/WritePreloadedClassFile.java
index d87b1f0..b209af0 100644
--- a/tools/preload/WritePreloadedClassFile.java
+++ b/tools/preload/WritePreloadedClassFile.java
@@ -20,8 +20,6 @@
 import java.io.OutputStreamWriter;
 import java.io.Writer;
 import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.List;
 import java.util.Set;
 import java.util.TreeSet;
 
@@ -32,71 +30,85 @@
 public class WritePreloadedClassFile {
 
     public static void main(String[] args) throws IOException, ClassNotFoundException {
-        
-        // Process command-line arguments first
-        List<String> wiredProcesses = new ArrayList<String>();
-        String inputFileName = null;
-        int argOffset = 0;
-        try {
-            while ("--preload-all-process".equals(args[argOffset])) {
-                argOffset++;
-                wiredProcesses.add(args[argOffset++]);
-            }
-            
-            inputFileName = args[argOffset++];
-        } catch (RuntimeException e) {
-            System.err.println("Usage: WritePreloadedClassFile " +
-                    "[--preload-all-process process-name] " +
-                    "[compiled log file]");
-            System.exit(0);
+        if (args.length != 1) {
+            System.err.println("Usage: WritePreloadedClassFile [compiled log]");
+            System.exit(-1);
         }
+        String rootFile = args[0];
+        Root root = Root.fromFile(rootFile);
 
-        Root root = Root.fromFile(inputFileName);
-
+        // No classes are preloaded to start.
         for (LoadedClass loadedClass : root.loadedClasses.values()) {
             loadedClass.preloaded = false;
         }
 
+        // Open preloaded-classes file for output.
         Writer out = new BufferedWriter(new OutputStreamWriter(
                 new FileOutputStream(Policy.getPreloadedClassFileName()),
                 Charset.forName("US-ASCII")));
 
         out.write("# Classes which are preloaded by com.android.internal.os.ZygoteInit.\n");
         out.write("# Automatically generated by /frameworks/base/tools/preload.\n");
-        out.write("# percent=" + Proc.PERCENTAGE_TO_PRELOAD + ", weight="
-                + ClassRank.SEQUENCE_WEIGHT
+        out.write("# percent=" + Proc.PERCENTAGE_TO_PRELOAD
+                + ", weight=" + ClassRank.SEQUENCE_WEIGHT
                 + ", bucket_size=" + ClassRank.BUCKET_SIZE
                 + "\n");
-        for (String wiredProcess : wiredProcesses) {
-            out.write("# forcing classes loaded by: " + wiredProcess + "\n");
-        }
 
-        Set<LoadedClass> highestRanked = new TreeSet<LoadedClass>();
-        for (Proc proc : root.processes.values()) {
-            // test to see if this is one of the wired-down ("take all classes") processes
-            boolean isWired = wiredProcesses.contains(proc.name);
-            
-            List<LoadedClass> highestForProc = proc.highestRankedClasses(isWired);
+        Set<LoadedClass> toPreload = new TreeSet<LoadedClass>();
 
-            System.out.println(proc.name + ": " + highestForProc.size());
-
-            for (LoadedClass loadedClass : highestForProc) {
-                loadedClass.preloaded = true;
+        // Preload all classes that were loaded by at least 2 apps, if both
+        // apps run at the same time, they'll share memory.
+        for (LoadedClass loadedClass : root.loadedClasses.values()) {
+            if (!loadedClass.isPreloadable()) {
+                continue;
             }
-            highestRanked.addAll(highestForProc);
+
+            Set<String> appNames = loadedClass.applicationNames();
+
+            if (appNames.size() > 3) {
+                toPreload.add(loadedClass);
+            }
         }
 
-        for (LoadedClass loadedClass : highestRanked) {
+        // Try to make individual apps start faster by preloading slowest
+        // classes.
+        for (Proc proc : root.processes.values()) {
+            toPreload.addAll(proc.highestRankedClasses());
+        }
+
+        System.out.println(toPreload.size() + " classes will be preloaded.");
+
+        // Make classes that were already loaded by the zygote explicit.
+        // This adds minimal overhead but avoid confusion about classes not
+        // appearing in the list.
+        addAllClassesFor("zygote", root, toPreload);
+
+        for (LoadedClass loadedClass : toPreload) {
             out.write(loadedClass.name);
             out.write('\n');
         }
 
         out.close();
 
-        System.out.println(highestRanked.size()
-                + " classes will be preloaded.");
-
         // Update data to reflect LoadedClass.preloaded changes.
-        root.toFile(inputFileName);
+        for (LoadedClass loadedClass : toPreload) {
+            loadedClass.preloaded = true;
+        }
+        root.toFile(rootFile);
+    }
+
+    private static void addAllClassesFor(String packageName, Root root,
+                                         Set<LoadedClass> toPreload) {
+        for (Proc proc : root.processes.values()) {
+            if (proc.name.equals(packageName)) {
+                for (Operation operation : proc.operations) {
+                    // TODO: I'm not sure how the zygote loaded classes that
+                    // aren't supposed to be preloadable...
+                    if (operation.loadedClass.isPreloadable()) {
+                        toPreload.add(operation.loadedClass);
+                    }
+                }
+            }
+        }
     }
 }
diff --git a/tools/preload/preload.iml b/tools/preload/preload.iml
index d1fab57..2d87c55 100644
--- a/tools/preload/preload.iml
+++ b/tools/preload/preload.iml
@@ -1,15 +1,14 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <module relativePaths="true" type="JAVA_MODULE" version="4">
   <component name="NewModuleRootManager" inherit-compiler-output="false">
-    <output url="file:///tmp/preload/" />
+    <output url="file:///tmp/preload" />
+    <output-test url="file:///tmp/preload" />
     <exclude-output />
-    <output-test url="file:///tmp/preload/" />
     <content url="file://$MODULE_DIR$">
       <sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
     </content>
     <orderEntry type="inheritedJdk" />
     <orderEntry type="sourceFolder" forTests="false" />
-    <orderEntryProperties />
   </component>
 </module>
 
diff --git a/tools/preload/preload.ipr b/tools/preload/preload.ipr
index c5613ad..f78bf76 100644
--- a/tools/preload/preload.ipr
+++ b/tools/preload/preload.ipr
@@ -114,6 +114,7 @@
     <option name="ADDITIONAL_OPTIONS_STRING" value="" />
     <option name="MAXIMUM_HEAP_SIZE" value="128" />
   </component>
+  <component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
   <component name="EntryPointsManager">
     <entry_points version="2.0" />
   </component>
@@ -125,13 +126,13 @@
   <component name="IdProvider" IDEtalkID="D171F99B9178C1675593DC9A76A5CC7E" />
   <component name="InspectionProjectProfileManager">
     <option name="PROJECT_PROFILE" value="Project Default" />
-    <option name="USE_PROJECT_LEVEL_SETTINGS" value="false" />
-    <scopes />
+    <option name="USE_PROJECT_PROFILE" value="true" />
+    <version value="1.0" />
     <profiles>
       <profile version="1.0" is_locked="false">
         <option name="myName" value="Project Default" />
         <option name="myLocal" value="false" />
-        <inspection_tool class="JavaDoc" level="WARNING" enabled="false">
+        <inspection_tool class="JavaDoc" enabled="false" level="WARNING" enabled_by_default="false">
           <option name="TOP_LEVEL_CLASS_OPTIONS">
             <value>
               <option name="ACCESS_JAVADOC_REQUIRED_FOR" value="none" />
@@ -160,14 +161,19 @@
           <option name="IGNORE_JAVADOC_PERIOD" value="true" />
           <option name="myAdditionalJavadocTags" value="" />
         </inspection_tool>
-        <inspection_tool class="OnDemandImport" level="WARNING" enabled="true" />
-        <inspection_tool class="SamePackageImport" level="WARNING" enabled="true" />
-        <inspection_tool class="JavaLangImport" level="WARNING" enabled="true" />
-        <inspection_tool class="RedundantImport" level="WARNING" enabled="true" />
-        <inspection_tool class="UnusedImport" level="WARNING" enabled="true" />
+        <inspection_tool class="JavaLangImport" enabled="true" level="WARNING" enabled_by_default="true" />
+        <inspection_tool class="OnDemandImport" enabled="true" level="WARNING" enabled_by_default="true" />
+        <inspection_tool class="RedundantImport" enabled="true" level="WARNING" enabled_by_default="true" />
+        <inspection_tool class="SamePackageImport" enabled="true" level="WARNING" enabled_by_default="true" />
+        <inspection_tool class="UnusedImport" enabled="true" level="WARNING" enabled_by_default="true" />
       </profile>
     </profiles>
-    <list size="0" />
+    <list size="4">
+      <item index="0" class="java.lang.String" itemvalue="WARNING" />
+      <item index="1" class="java.lang.String" itemvalue="SERVER PROBLEM" />
+      <item index="2" class="java.lang.String" itemvalue="INFO" />
+      <item index="3" class="java.lang.String" itemvalue="ERROR" />
+    </list>
   </component>
   <component name="JavacSettings">
     <option name="DEBUGGING_INFO" value="true" />
@@ -332,13 +338,19 @@
     <option name="USE_CLIENT_FILTER" value="true" />
     <option name="CLIENT" value="" />
   </component>
+  <component name="ProjectDetails">
+    <option name="projectName" value="preload" />
+  </component>
   <component name="ProjectFileVersion" converted="true" />
+  <component name="ProjectKey">
+    <option name="state" value="project:///Volumes/Android/donut/frameworks/base/tools/preload/preload.ipr" />
+  </component>
   <component name="ProjectModuleManager">
     <modules>
       <module fileurl="file://$PROJECT_DIR$/preload.iml" filepath="$PROJECT_DIR$/preload.iml" />
     </modules>
   </component>
-  <component name="ProjectRootManager" version="2" assert-keyword="true" jdk-15="true" project-jdk-name="1.5" project-jdk-type="JavaSDK">
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_5" assert-keyword="true" jdk-15="true" project-jdk-name="1.5" project-jdk-type="JavaSDK">
     <output url="file:///tmp/preload" />
   </component>
   <component name="RmicSettings">
@@ -374,6 +386,9 @@
     <option name="myValidatorValidationEnabled" value="true" />
     <option name="myReportErrorsAsWarnings" value="true" />
   </component>
+  <component name="SvnBranchConfigurationManager">
+    <option name="mySupportsUserInfoFilter" value="true" />
+  </component>
   <component name="SvnChangesBrowserSettings">
     <option name="USE_AUTHOR_FIELD" value="true" />
     <option name="AUTHOR" value="" />
@@ -381,15 +396,6 @@
     <option name="USE_PROJECT_SETTINGS" value="true" />
     <option name="USE_ALTERNATE_LOCATION" value="false" />
   </component>
-  <component name="SvnConfiguration">
-    <option name="USER" value="" />
-    <option name="PASSWORD" value="" />
-    <option name="PROCESS_UNRESOLVED" value="false" />
-    <option name="LAST_MERGED_REVISION" />
-    <option name="UPDATE_RUN_STATUS" value="false" />
-    <option name="UPDATE_RECURSIVELY" value="true" />
-    <option name="MERGE_DRY_RUN" value="false" />
-  </component>
   <component name="VCS.FileViewConfiguration">
     <option name="SELECTED_STATUSES" value="DEFAULT" />
     <option name="SELECTED_COLUMNS" value="DEFAULT" />