Merge "when test case times out, stop loading first" into honeycomb
diff --git a/api/11.xml b/api/11.xml
index 1bcf563..34a7a5c 100644
--- a/api/11.xml
+++ b/api/11.xml
@@ -7616,6 +7616,17 @@
  visibility="public"
 >
 </field>
+<field name="queryHint"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843610"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="quickContactBadgeStyleSmallWindowLarge"
  type="int"
  transient="false"
@@ -14860,7 +14871,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974053"
+ value="16974054"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -14871,7 +14882,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974055"
+ value="16974056"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -14882,7 +14893,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974054"
+ value="16974055"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -14893,7 +14904,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974056"
+ value="16974057"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -14904,7 +14915,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974058"
+ value="16974059"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -14915,7 +14926,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974057"
+ value="16974058"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15234,7 +15245,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973952"
+ value="16973953"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15245,7 +15256,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973953"
+ value="16973954"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15439,6 +15450,17 @@
  visibility="public"
 >
 </field>
+<field name="Theme_Holo_InputMethod"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973952"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="Theme_Holo_Light"
  type="int"
  transient="false"
@@ -15828,7 +15850,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973954"
+ value="16973955"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15839,7 +15861,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973956"
+ value="16973957"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15850,7 +15872,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973960"
+ value="16973961"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15861,7 +15883,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973959"
+ value="16973960"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15927,7 +15949,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974068"
+ value="16974069"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16015,7 +16037,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974060"
+ value="16974061"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16037,7 +16059,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973961"
+ value="16973962"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16070,7 +16092,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973962"
+ value="16973963"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16081,7 +16103,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974004"
+ value="16974005"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16092,7 +16114,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973999"
+ value="16974000"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16103,7 +16125,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974003"
+ value="16974004"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16114,7 +16136,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974000"
+ value="16974001"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16125,7 +16147,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974001"
+ value="16974002"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16136,7 +16158,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974002"
+ value="16974003"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16147,7 +16169,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973968"
+ value="16973969"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16158,7 +16180,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973963"
+ value="16973964"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16169,7 +16191,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974050"
+ value="16974051"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16180,7 +16202,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973965"
+ value="16973966"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16191,7 +16213,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973964"
+ value="16973965"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16202,7 +16224,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973966"
+ value="16973967"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16213,7 +16235,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974069"
+ value="16974070"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16224,7 +16246,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973969"
+ value="16973970"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16235,7 +16257,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973986"
+ value="16973987"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16246,7 +16268,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973990"
+ value="16973991"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16257,7 +16279,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973994"
+ value="16973995"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16268,7 +16290,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973995"
+ value="16973996"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16279,7 +16301,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973971"
+ value="16973972"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16290,7 +16312,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974063"
+ value="16974064"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16301,7 +16323,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973972"
+ value="16973973"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16312,7 +16334,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973973"
+ value="16973974"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16323,7 +16345,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973988"
+ value="16973989"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16334,7 +16356,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973974"
+ value="16973975"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16345,7 +16367,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974064"
+ value="16974065"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16356,7 +16378,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974062"
+ value="16974063"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16367,7 +16389,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974005"
+ value="16974006"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16378,7 +16400,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974049"
+ value="16974050"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16389,7 +16411,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974045"
+ value="16974046"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16400,7 +16422,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974048"
+ value="16974049"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16411,7 +16433,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974046"
+ value="16974047"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16422,7 +16444,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974047"
+ value="16974048"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16433,7 +16455,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974011"
+ value="16974012"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16444,7 +16466,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974006"
+ value="16974007"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16455,7 +16477,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974008"
+ value="16974009"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16466,7 +16488,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974007"
+ value="16974008"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16477,7 +16499,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974009"
+ value="16974010"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16488,7 +16510,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974070"
+ value="16974071"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16499,7 +16521,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974012"
+ value="16974013"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16510,7 +16532,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974032"
+ value="16974033"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16521,7 +16543,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974036"
+ value="16974037"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16532,7 +16554,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974040"
+ value="16974041"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16543,7 +16565,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974041"
+ value="16974042"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16554,7 +16576,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974014"
+ value="16974015"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16565,7 +16587,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974066"
+ value="16974067"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16576,7 +16598,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974015"
+ value="16974016"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16587,7 +16609,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974016"
+ value="16974017"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16598,7 +16620,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974034"
+ value="16974035"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16609,7 +16631,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974017"
+ value="16974018"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16620,7 +16642,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974067"
+ value="16974068"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16631,7 +16653,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974065"
+ value="16974066"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16642,7 +16664,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974043"
+ value="16974044"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16653,7 +16675,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974018"
+ value="16974019"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16664,7 +16686,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974013"
+ value="16974014"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16675,7 +16697,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974044"
+ value="16974045"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16686,7 +16708,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974019"
+ value="16974020"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16697,7 +16719,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974020"
+ value="16974021"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16708,7 +16730,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974021"
+ value="16974022"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16719,7 +16741,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974025"
+ value="16974026"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16730,7 +16752,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974024"
+ value="16974025"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16741,7 +16763,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974027"
+ value="16974028"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16752,7 +16774,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974022"
+ value="16974023"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16763,7 +16785,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974026"
+ value="16974027"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16774,7 +16796,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974023"
+ value="16974024"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16785,7 +16807,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974029"
+ value="16974030"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16796,7 +16818,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974030"
+ value="16974031"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16807,7 +16829,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974031"
+ value="16974032"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16818,7 +16840,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974033"
+ value="16974034"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16829,7 +16851,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974028"
+ value="16974029"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16840,7 +16862,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974035"
+ value="16974036"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16851,7 +16873,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974052"
+ value="16974053"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16862,7 +16884,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974037"
+ value="16974038"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16873,7 +16895,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974010"
+ value="16974011"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16884,7 +16906,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974042"
+ value="16974043"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16895,7 +16917,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974038"
+ value="16974039"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16906,7 +16928,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974039"
+ value="16974040"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16917,7 +16939,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973997"
+ value="16973998"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16928,7 +16950,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973975"
+ value="16973976"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16939,7 +16961,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973970"
+ value="16973971"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16950,7 +16972,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973998"
+ value="16973999"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16961,7 +16983,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973976"
+ value="16973977"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16972,7 +16994,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973977"
+ value="16973978"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16983,7 +17005,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973978"
+ value="16973979"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16994,7 +17016,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973981"
+ value="16973982"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17005,7 +17027,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973979"
+ value="16973980"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17016,7 +17038,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973980"
+ value="16973981"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17027,7 +17049,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973983"
+ value="16973984"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17038,7 +17060,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973984"
+ value="16973985"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17049,7 +17071,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973985"
+ value="16973986"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17060,7 +17082,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973987"
+ value="16973988"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17071,7 +17093,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973982"
+ value="16973983"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17082,7 +17104,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973989"
+ value="16973990"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17093,7 +17115,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974051"
+ value="16974052"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17104,7 +17126,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973991"
+ value="16973992"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17115,7 +17137,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973967"
+ value="16973968"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17126,7 +17148,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973996"
+ value="16973997"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17137,7 +17159,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973992"
+ value="16973993"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17148,7 +17170,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973993"
+ value="16973994"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17170,7 +17192,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974061"
+ value="16974062"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17181,7 +17203,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974059"
+ value="16974060"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17214,7 +17236,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973957"
+ value="16973958"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17269,7 +17291,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973958"
+ value="16973959"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17412,7 +17434,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973955"
+ value="16973956"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -37232,6 +37254,17 @@
  visibility="public"
 >
 </field>
+<field name="USES_ENCRYPTED_STORAGE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="USES_POLICY_EXPIRE_PASSWORD"
  type="int"
  transient="false"
@@ -37795,6 +37828,19 @@
 <parameter name="admin" type="android.content.ComponentName">
 </parameter>
 </method>
+<method name="getStorageEncryption"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+</method>
 <method name="hasGrantedPolicy"
  return="boolean"
  abstract="false"
@@ -38070,6 +38116,21 @@
 <parameter name="quality" type="int">
 </parameter>
 </method>
+<method name="setStorageEncryption"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="admin" type="android.content.ComponentName">
+</parameter>
+<parameter name="encrypt" type="boolean">
+</parameter>
+</method>
 <method name="wipeData"
  return="void"
  abstract="false"
@@ -38105,6 +38166,72 @@
  visibility="public"
 >
 </field>
+<field name="ACTION_START_ENCRYPTION"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;android.app.action.START_ENCRYPTION&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ENCRYPTION_STATUS_ACTIVATING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ENCRYPTION_STATUS_ACTIVE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ENCRYPTION_STATUS_INACTIVE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ENCRYPTION_STATUS_REQUESTED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ENCRYPTION_STATUS_UNSUPPORTED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="EXTRA_ADD_EXPLANATION"
  type="java.lang.String"
  transient="false"
@@ -86104,6 +86231,19 @@
 <parameter name="texName" type="int">
 </parameter>
 </constructor>
+<method name="getTransformMatrix"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="mtx" type="float[]">
+</parameter>
+</method>
 <method name="setOnFrameAvailableListener"
  return="void"
  abstract="false"
@@ -167047,7 +167187,7 @@
 </parameter>
 <parameter name="type" type="android.renderscript.Type">
 </parameter>
-<parameter name="mc" type="android.renderscript.Allocation.MipmapControl">
+<parameter name="mips" type="android.renderscript.Allocation.MipmapControl">
 </parameter>
 <parameter name="usage" type="int">
 </parameter>
@@ -168910,52 +169050,6 @@
 >
 </method>
 </class>
-<class name="FileA3D.ClassID"
- extends="java.lang.Enum"
- abstract="false"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-<method name="toClassID"
- return="android.renderscript.FileA3D.ClassID"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="intID" type="int">
-</parameter>
-</method>
-<method name="valueOf"
- return="android.renderscript.FileA3D.ClassID"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="name" type="java.lang.String">
-</parameter>
-</method>
-<method name="values"
- return="android.renderscript.FileA3D.ClassID[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-</class>
 <class name="FileA3D.EntryType"
  extends="java.lang.Enum"
  abstract="false"
@@ -168997,17 +169091,6 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<method name="getClassID"
- return="android.renderscript.FileA3D.ClassID"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="getEntryType"
  return="android.renderscript.FileA3D.EntryType"
  abstract="false"
@@ -171048,50 +171131,6 @@
 <exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
 </exception>
 </method>
-<field name="MAX_CONSTANT"
- type="int"
- transient="false"
- volatile="false"
- value="8"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="MAX_INPUT"
- type="int"
- transient="false"
- volatile="false"
- value="8"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="MAX_OUTPUT"
- type="int"
- transient="false"
- volatile="false"
- value="8"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="MAX_TEXTURE"
- type="int"
- transient="false"
- volatile="false"
- value="8"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 </class>
 <class name="Program.BaseProgramBuilder"
  extends="java.lang.Object"
@@ -260097,7 +260136,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="t" type="T">
+<parameter name="arg0" type="T">
 </parameter>
 </method>
 </interface>
diff --git a/api/current.xml b/api/current.xml
index 0c33b8c..f417e3d 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -7616,6 +7616,17 @@
  visibility="public"
 >
 </field>
+<field name="queryHint"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843610"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="quickContactBadgeStyleSmallWindowLarge"
  type="int"
  transient="false"
@@ -14860,7 +14871,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974053"
+ value="16974054"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -14871,7 +14882,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974055"
+ value="16974056"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -14882,7 +14893,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974054"
+ value="16974055"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -14893,7 +14904,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974056"
+ value="16974057"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -14904,7 +14915,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974058"
+ value="16974059"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -14915,7 +14926,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974057"
+ value="16974058"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15234,7 +15245,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973952"
+ value="16973953"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15245,7 +15256,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973953"
+ value="16973954"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15439,6 +15450,17 @@
  visibility="public"
 >
 </field>
+<field name="Theme_Holo_InputMethod"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16973952"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="Theme_Holo_Light"
  type="int"
  transient="false"
@@ -15828,7 +15850,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973954"
+ value="16973955"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15839,7 +15861,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973956"
+ value="16973957"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15850,7 +15872,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973960"
+ value="16973961"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15861,7 +15883,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973959"
+ value="16973960"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -15927,7 +15949,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974068"
+ value="16974069"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16015,7 +16037,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974060"
+ value="16974061"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16037,7 +16059,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973961"
+ value="16973962"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16070,7 +16092,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973962"
+ value="16973963"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16081,7 +16103,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974004"
+ value="16974005"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16092,7 +16114,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973999"
+ value="16974000"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16103,7 +16125,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974003"
+ value="16974004"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16114,7 +16136,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974000"
+ value="16974001"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16125,7 +16147,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974001"
+ value="16974002"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16136,7 +16158,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974002"
+ value="16974003"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16147,7 +16169,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973968"
+ value="16973969"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16158,7 +16180,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973963"
+ value="16973964"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16169,7 +16191,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974050"
+ value="16974051"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16180,7 +16202,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973965"
+ value="16973966"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16191,7 +16213,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973964"
+ value="16973965"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16202,7 +16224,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973966"
+ value="16973967"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16213,7 +16235,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974069"
+ value="16974070"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16224,7 +16246,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973969"
+ value="16973970"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16235,7 +16257,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973986"
+ value="16973987"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16246,7 +16268,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973990"
+ value="16973991"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16257,7 +16279,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973994"
+ value="16973995"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16268,7 +16290,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973995"
+ value="16973996"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16279,7 +16301,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973971"
+ value="16973972"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16290,7 +16312,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974063"
+ value="16974064"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16301,7 +16323,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973972"
+ value="16973973"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16312,7 +16334,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973973"
+ value="16973974"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16323,7 +16345,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973988"
+ value="16973989"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16334,7 +16356,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973974"
+ value="16973975"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16345,7 +16367,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974064"
+ value="16974065"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16356,7 +16378,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974062"
+ value="16974063"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16367,7 +16389,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974005"
+ value="16974006"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16378,7 +16400,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974049"
+ value="16974050"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16389,7 +16411,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974045"
+ value="16974046"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16400,7 +16422,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974048"
+ value="16974049"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16411,7 +16433,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974046"
+ value="16974047"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16422,7 +16444,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974047"
+ value="16974048"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16433,7 +16455,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974011"
+ value="16974012"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16444,7 +16466,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974006"
+ value="16974007"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16455,7 +16477,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974008"
+ value="16974009"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16466,7 +16488,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974007"
+ value="16974008"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16477,7 +16499,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974009"
+ value="16974010"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16488,7 +16510,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974070"
+ value="16974071"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16499,7 +16521,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974012"
+ value="16974013"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16510,7 +16532,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974032"
+ value="16974033"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16521,7 +16543,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974036"
+ value="16974037"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16532,7 +16554,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974040"
+ value="16974041"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16543,7 +16565,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974041"
+ value="16974042"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16554,7 +16576,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974014"
+ value="16974015"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16565,7 +16587,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974066"
+ value="16974067"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16576,7 +16598,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974015"
+ value="16974016"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16587,7 +16609,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974016"
+ value="16974017"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16598,7 +16620,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974034"
+ value="16974035"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16609,7 +16631,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974017"
+ value="16974018"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16620,7 +16642,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974067"
+ value="16974068"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16631,7 +16653,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974065"
+ value="16974066"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16642,7 +16664,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974043"
+ value="16974044"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16653,7 +16675,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974018"
+ value="16974019"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16664,7 +16686,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974013"
+ value="16974014"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16675,7 +16697,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974044"
+ value="16974045"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16686,7 +16708,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974019"
+ value="16974020"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16697,7 +16719,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974020"
+ value="16974021"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16708,7 +16730,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974021"
+ value="16974022"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16719,7 +16741,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974025"
+ value="16974026"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16730,7 +16752,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974024"
+ value="16974025"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16741,7 +16763,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974027"
+ value="16974028"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16752,7 +16774,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974022"
+ value="16974023"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16763,7 +16785,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974026"
+ value="16974027"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16774,7 +16796,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974023"
+ value="16974024"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16785,7 +16807,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974029"
+ value="16974030"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16796,7 +16818,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974030"
+ value="16974031"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16807,7 +16829,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974031"
+ value="16974032"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16818,7 +16840,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974033"
+ value="16974034"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16829,7 +16851,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974028"
+ value="16974029"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16840,7 +16862,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974035"
+ value="16974036"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16851,7 +16873,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974052"
+ value="16974053"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16862,7 +16884,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974037"
+ value="16974038"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16873,7 +16895,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974010"
+ value="16974011"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16884,7 +16906,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974042"
+ value="16974043"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16895,7 +16917,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974038"
+ value="16974039"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16906,7 +16928,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974039"
+ value="16974040"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16917,7 +16939,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973997"
+ value="16973998"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16928,7 +16950,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973975"
+ value="16973976"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16939,7 +16961,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973970"
+ value="16973971"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16950,7 +16972,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973998"
+ value="16973999"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16961,7 +16983,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973976"
+ value="16973977"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16972,7 +16994,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973977"
+ value="16973978"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16983,7 +17005,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973978"
+ value="16973979"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -16994,7 +17016,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973981"
+ value="16973982"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17005,7 +17027,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973979"
+ value="16973980"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17016,7 +17038,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973980"
+ value="16973981"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17027,7 +17049,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973983"
+ value="16973984"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17038,7 +17060,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973984"
+ value="16973985"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17049,7 +17071,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973985"
+ value="16973986"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17060,7 +17082,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973987"
+ value="16973988"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17071,7 +17093,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973982"
+ value="16973983"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17082,7 +17104,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973989"
+ value="16973990"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17093,7 +17115,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974051"
+ value="16974052"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17104,7 +17126,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973991"
+ value="16973992"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17115,7 +17137,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973967"
+ value="16973968"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17126,7 +17148,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973996"
+ value="16973997"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17137,7 +17159,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973992"
+ value="16973993"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17148,7 +17170,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973993"
+ value="16973994"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17170,7 +17192,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974061"
+ value="16974062"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17181,7 +17203,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16974059"
+ value="16974060"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17214,7 +17236,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973957"
+ value="16973958"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17269,7 +17291,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973958"
+ value="16973959"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -17412,7 +17434,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16973955"
+ value="16973956"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -38961,6 +38983,17 @@
  visibility="public"
 >
 </method>
+<method name="clearViews"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="protected"
+>
+</method>
 <method name="createView"
  return="android.appwidget.AppWidgetHostView"
  abstract="false"
@@ -60234,6 +60267,19 @@
 <exception name="PackageManager.NameNotFoundException" type="android.content.pm.PackageManager.NameNotFoundException">
 </exception>
 </method>
+<method name="getPackageObbPaths"
+ return="java.lang.String[]"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="packageName" type="java.lang.String">
+</parameter>
+</method>
 <method name="getPackagesForUid"
  return="java.lang.String[]"
  abstract="true"
@@ -60720,6 +60766,21 @@
 <parameter name="installerPackageName" type="java.lang.String">
 </parameter>
 </method>
+<method name="setPackageObbPaths"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="packageName" type="java.lang.String">
+</parameter>
+<parameter name="paths" type="java.lang.String[]">
+</parameter>
+</method>
 <field name="COMPONENT_ENABLED_STATE_DEFAULT"
  type="int"
  transient="false"
@@ -167165,7 +167226,7 @@
 </parameter>
 <parameter name="type" type="android.renderscript.Type">
 </parameter>
-<parameter name="mc" type="android.renderscript.Allocation.MipmapControl">
+<parameter name="mips" type="android.renderscript.Allocation.MipmapControl">
 </parameter>
 <parameter name="usage" type="int">
 </parameter>
@@ -169028,52 +169089,6 @@
 >
 </method>
 </class>
-<class name="FileA3D.ClassID"
- extends="java.lang.Enum"
- abstract="false"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-<method name="toClassID"
- return="android.renderscript.FileA3D.ClassID"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="intID" type="int">
-</parameter>
-</method>
-<method name="valueOf"
- return="android.renderscript.FileA3D.ClassID"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="name" type="java.lang.String">
-</parameter>
-</method>
-<method name="values"
- return="android.renderscript.FileA3D.ClassID[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-</class>
 <class name="FileA3D.EntryType"
  extends="java.lang.Enum"
  abstract="false"
@@ -169115,17 +169130,6 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<method name="getClassID"
- return="android.renderscript.FileA3D.ClassID"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="getEntryType"
  return="android.renderscript.FileA3D.EntryType"
  abstract="false"
@@ -171166,50 +171170,6 @@
 <exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
 </exception>
 </method>
-<field name="MAX_CONSTANT"
- type="int"
- transient="false"
- volatile="false"
- value="8"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="MAX_INPUT"
- type="int"
- transient="false"
- volatile="false"
- value="8"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="MAX_OUTPUT"
- type="int"
- transient="false"
- volatile="false"
- value="8"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="MAX_TEXTURE"
- type="int"
- transient="false"
- volatile="false"
- value="8"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 </class>
 <class name="Program.BaseProgramBuilder"
  extends="java.lang.Object"
@@ -185286,6 +185246,19 @@
 <exception name="PackageManager.NameNotFoundException" type="android.content.pm.PackageManager.NameNotFoundException">
 </exception>
 </method>
+<method name="getPackageObbPaths"
+ return="java.lang.String[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="packageName" type="java.lang.String">
+</parameter>
+</method>
 <method name="getPackagesForUid"
  return="java.lang.String[]"
  abstract="false"
@@ -185785,6 +185758,21 @@
 <parameter name="path" type="java.lang.String">
 </parameter>
 </method>
+<method name="setPackageObbPaths"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="packageName" type="java.lang.String">
+</parameter>
+<parameter name="paths" type="java.lang.String[]">
+</parameter>
+</method>
 </class>
 <class name="MockResources"
  extends="android.content.res.Resources"
@@ -238199,6 +238187,34 @@
 >
 </field>
 </class>
+<class name="WebViewFragment"
+ extends="android.app.Fragment"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="WebViewFragment"
+ type="android.webkit.WebViewFragment"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="getWebView"
+ return="android.webkit.WebView"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
 </package>
 <package name="android.widget"
 >
@@ -260215,7 +260231,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="t" type="T">
+<parameter name="arg0" type="T">
 </parameter>
 </method>
 </interface>
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 6e04587..9cbc7be 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -861,7 +861,7 @@
 
     public void getAuthToken(IAccountManagerResponse response, final Account account,
             final String authTokenType, final boolean notifyOnAuthFailure,
-            final boolean expectActivityLaunch, final Bundle loginOptions) {
+            final boolean expectActivityLaunch, Bundle loginOptionsIn) {
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
             Log.v(TAG, "getAuthToken: " + account
                     + ", response " + response
@@ -888,6 +888,8 @@
         final boolean permissionGranted = customTokens ||
             permissionIsGranted(account, authTokenType, callerUid);
 
+        final Bundle loginOptions = (loginOptionsIn == null) ? new Bundle() :
+            loginOptionsIn;
         if (customTokens) {
             // let authenticator know the identity of the caller
             loginOptions.putInt(AccountManager.KEY_CALLER_UID, callerUid);
diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java
index 7f11871..3212cba 100644
--- a/core/java/android/animation/ObjectAnimator.java
+++ b/core/java/android/animation/ObjectAnimator.java
@@ -18,6 +18,7 @@
 
 import android.util.Log;
 
+import java.lang.ref.WeakReference;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 
@@ -28,6 +29,8 @@
  * are then determined internally and the animation will call these functions as necessary to
  * animate the property.
  *
+ * <p class="note"><b>Note:</b> Instances of this class hold only a {@link WeakReference}
+ * to the target object.</p>
  * @see #setPropertyName(String)
  *
  */
@@ -35,7 +38,7 @@
     private static final boolean DBG = false;
 
     // The target object on which the property exists, set in the constructor
-    private Object mTarget;
+    private WeakReference<Object> mTargetRef;
 
     private String mPropertyName;
 
@@ -102,6 +105,9 @@
      * @return Method the method associated with mPropertyName.
      */
     private Method getPropertyFunction(String prefix, Class valueType) {
+        final Object target = mTargetRef == null ? null : mTargetRef.get();
+        if (target == null) return null;
+
         // TODO: faster implementation...
         Method returnVal = null;
         String firstLetter = mPropertyName.substring(0, 1);
@@ -114,7 +120,7 @@
             args[0] = valueType;
         }
         try {
-            returnVal = mTarget.getClass().getMethod(setterName, args);
+            returnVal = target.getClass().getMethod(setterName, args);
         } catch (NoSuchMethodException e) {
             Log.e("ObjectAnimator",
                     "Couldn't find setter/getter for property " + mPropertyName + ": " + e);
@@ -134,13 +140,14 @@
      * A constructor that takes a single property name and set of values. This constructor is
      * used in the simple case of animating a single property.
      *
-     * @param target The object whose property is to be animated. This object should
-     * have a public method on it called <code>setName()</code>, where <code>name</code> is
-     * the value of the <code>propertyName</code> parameter.
+     * @param target The object whose property is to be animated. It will be weakly referenced
+     * from the newly-created ObjectAnimator. This object should have a public method on it called
+     * <code>setName()</code>, where <code>name</code> is the value of the <code>propertyName</code>
+     * parameter.
      * @param propertyName The name of the property being animated.
      */
     private ObjectAnimator(Object target, String propertyName) {
-        mTarget = target;
+        mTargetRef = new WeakReference<Object>(target);
         setPropertyName(propertyName);
     }
 
@@ -152,9 +159,10 @@
      * from the target object and property being animated). Therefore, there should typically
      * be two or more values.
      *
-     * @param target The object whose property is to be animated. This object should
-     * have a public method on it called <code>setName()</code>, where <code>name</code> is
-     * the value of the <code>propertyName</code> parameter.
+     * @param target The object whose property is to be animated. It will be weakly referenced
+     * from the newly-created ObjectAnimator. This object should have a public method on it called
+     * <code>setName()</code>, where <code>name</code> is the value of the <code>propertyName</code>
+     * parameter.
      * @param propertyName The name of the property being animated.
      * @param values A set of values that the animation will animate between over time.
      * @return A ValueAnimator object that is set up to animate between the given values.
@@ -173,9 +181,10 @@
      * from the target object and property being animated). Therefore, there should typically
      * be two or more values.
      *
-     * @param target The object whose property is to be animated. This object should
-     * have a public method on it called <code>setName()</code>, where <code>name</code> is
-     * the value of the <code>propertyName</code> parameter.
+     * @param target The object whose property is to be animated. It will be weakly referenced
+     * from the newly-created ObjectAnimator. This object should have a public method on it called
+     * <code>setName()</code>, where <code>name</code> is the value of the <code>propertyName</code>
+     * parameter.
      * @param propertyName The name of the property being animated.
      * @param values A set of values that the animation will animate between over time.
      * @return A ValueAnimator object that is set up to animate between the given values.
@@ -192,10 +201,10 @@
      * PropertyValuesHolder allows you to associate a set of animation values with a property
      * name.
      *
-     * @param target The object whose property is to be animated. This object should
-     * have public methods on it called <code>setName()</code>, where <code>name</code> is
-     * the name of the property passed in as the <code>propertyName</code> parameter for
-     * each of the PropertyValuesHolder objects.
+     * @param target The object whose property is to be animated. It will be weakly referenced
+     * from the newly-created ObjectAnimator. This object should have public methods on it called
+     * <code>setName()</code>, where <code>name</code> is the name of the property passed in as the
+     * <code>propertyName</code> parameter for each of the PropertyValuesHolder objects.
      * @param propertyName The name of the property being animated.
      * @param evaluator A TypeEvaluator that will be called on each animation frame to
      * provide the ncessry interpolation between the Object values to derive the animated
@@ -218,10 +227,10 @@
      * PropertyValuesHolder allows you to associate a set of animation values with a property
      * name.
      *
-     * @param target The object whose property is to be animated. This object should
-     * have public methods on it called <code>setName()</code>, where <code>name</code> is
-     * the name of the property passed in as the <code>propertyName</code> parameter for
-     * each of the PropertyValuesHolder objects.
+     * @param target The object whose property is to be animated. It will be weakly referenced
+     * from the newly-created ObjectAnimator. This object should have public methods on it called
+     * <code>setName()</code>, where <code>name</code> is the name of the property passed in as the
+     * <code>propertyName</code> parameter for each of the PropertyValuesHolder objects.
      * @param values A set of PropertyValuesHolder objects whose values will be animated
      * between over time.
      * @return A ValueAnimator object that is set up to animate between the given values.
@@ -229,7 +238,7 @@
     public static ObjectAnimator ofPropertyValuesHolder(Object target,
             PropertyValuesHolder... values) {
         ObjectAnimator anim = new ObjectAnimator();
-        anim.mTarget = target;
+        anim.mTargetRef = new WeakReference<Object>(target);
         anim.setValues(values);
         return anim;
     }
@@ -270,7 +279,8 @@
     @Override
     public void start() {
         if (DBG) {
-            Log.d("ObjectAnimator", "Anim target, duration" + mTarget + ", " + getDuration());
+            final Object target = mTargetRef == null ? null : mTargetRef.get();
+            Log.d("ObjectAnimator", "Anim target, duration" + target + ", " + getDuration());
             for (int i = 0; i < mValues.length; ++i) {
                 PropertyValuesHolder pvh = mValues[i];
                 ArrayList<Keyframe> keyframes = pvh.mKeyframeSet.mKeyframes;
@@ -297,11 +307,14 @@
     @Override
     void initAnimation() {
         if (!mInitialized) {
+            final Object target = mTargetRef == null ? null : mTargetRef.get();
+            if (target == null) return;
+
             // mValueType may change due to setter/getter setup; do this before calling super.init(),
             // which uses mValueType to set up the default type evaluator.
             int numValues = mValues.length;
             for (int i = 0; i < numValues; ++i) {
-                mValues[i].setupSetterAndGetter(mTarget);
+                mValues[i].setupSetterAndGetter(target);
             }
             super.initAnimation();
         }
@@ -326,22 +339,26 @@
     /**
      * The target object whose property will be animated by this animation
      *
-     * @return The object being animated
+     * @return The object being animated, or null if the object has been garbage collected.
      */
     public Object getTarget() {
-        return mTarget;
+        return mTargetRef == null ? null : mTargetRef.get();
     }
 
     /**
-     * Sets the target object whose property will be animated by this animation
+     * Sets the target object whose property will be animated by this animation. The target
+     * will be weakly referenced from this object.
      *
      * @param target The object being animated
      */
     @Override
     public void setTarget(Object target) {
-        if (mTarget != target) {
-            mTarget = target;
-            if (mTarget  != null && target != null && mTarget.getClass() == target.getClass()) {
+        final Object currentTarget = mTargetRef == null ? null : mTargetRef.get();
+
+        if (currentTarget != target) {
+            mTargetRef = new WeakReference<Object>(target);
+            if (currentTarget != null && target != null
+                    && currentTarget.getClass() == target.getClass()) {
                 return;
             }
             // New target type should cause re-initialization prior to starting
@@ -351,19 +368,25 @@
 
     @Override
     public void setupStartValues() {
+        final Object target = mTargetRef == null ? null : mTargetRef.get();
+        if (target == null) return;
+
         initAnimation();
         int numValues = mValues.length;
         for (int i = 0; i < numValues; ++i) {
-            mValues[i].setupStartValue(mTarget);
+            mValues[i].setupStartValue(target);
         }
     }
 
     @Override
     public void setupEndValues() {
+        final Object target = mTargetRef == null ? null : mTargetRef.get();
+        if (target == null) return;
+
         initAnimation();
         int numValues = mValues.length;
         for (int i = 0; i < numValues; ++i) {
-            mValues[i].setupEndValue(mTarget);
+            mValues[i].setupEndValue(target);
         }
     }
 
@@ -382,9 +405,13 @@
     @Override
     void animateValue(float fraction) {
         super.animateValue(fraction);
+
+        final Object target = mTargetRef == null ? null : mTargetRef.get();
+        if (target == null) return;
+
         int numValues = mValues.length;
         for (int i = 0; i < numValues; ++i) {
-            mValues[i].setAnimatedValue(mTarget);
+            mValues[i].setAnimatedValue(target);
         }
     }
 
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 4018703..b64069d 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1104,14 +1104,24 @@
     }
 
     @Override
-    public void setPackageObbPath(String packageName, String path) {
+    public void setPackageObbPaths(String packageName, String[] paths) {
         try {
-            mPM.setPackageObbPath(packageName, path);
+            mPM.setPackageObbPaths(packageName, paths);
         } catch (RemoteException e) {
             // Should never happen!
         }
     }
 
+    @Override
+    public String[] getPackageObbPaths(String packageName) {
+        try {
+            return mPM.getPackageObbPaths(packageName);
+        } catch (RemoteException e) {
+            // Should never happen!
+        }
+        return null;
+    }
+
     private final ContextImpl mContext;
     private final IPackageManager mPM;
 
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 16d3a7f..e133ea0 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -17,9 +17,6 @@
 package android.app;
 
 import com.android.internal.policy.PolicyManager;
-import com.android.internal.util.XmlUtils;
-
-import org.xmlpull.v1.XmlPullParserException;
 
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -35,14 +32,7 @@
 import android.content.ServiceConnection;
 import android.content.SharedPreferences;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.ComponentInfo;
-import android.content.pm.FeatureInfo;
-import android.content.pm.IPackageDataObserver;
-import android.content.pm.IPackageDeleteObserver;
-import android.content.pm.IPackageInstallObserver;
-import android.content.pm.IPackageMoveObserver;
 import android.content.pm.IPackageManager;
-import android.content.pm.IPackageStatsObserver;
 import android.content.pm.PackageManager;
 import android.content.res.AssetManager;
 import android.content.res.Resources;
@@ -80,14 +70,12 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.Vibrator;
-import android.os.FileUtils.FileStatus;
 import android.os.storage.StorageManager;
 import android.telephony.TelephonyManager;
 import android.content.ClipboardManager;
 import android.util.AndroidRuntimeException;
 import android.util.Log;
 import android.view.ContextThemeWrapper;
-import android.view.LayoutInflater;
 import android.view.WindowManagerImpl;
 import android.view.accessibility.AccessibilityManager;
 import android.view.inputmethod.InputMethodManager;
@@ -104,9 +92,6 @@
 import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
 
 class ReceiverRestrictedContext extends ContextWrapper {
     ReceiverRestrictedContext(Context base) {
@@ -354,10 +339,10 @@
                     final Context outerContext = ctx.getOuterContext();
                     return new NotificationManager(
                         new ContextThemeWrapper(outerContext,
-                                outerContext.getApplicationInfo().targetSdkVersion >=
-                                    Build.VERSION_CODES.HONEYCOMB
-                                ? com.android.internal.R.style.Theme_Holo_Dialog
-                                : com.android.internal.R.style.Theme_Dialog),
+                                Resources.selectSystemTheme(0,
+                                        outerContext.getApplicationInfo().targetSdkVersion,
+                                        com.android.internal.R.style.Theme_Dialog,
+                                        com.android.internal.R.style.Theme_Holo_Dialog)),
                         ctx.mMainThread.getHandler());
                 }});
 
@@ -492,13 +477,8 @@
     @Override
     public Resources.Theme getTheme() {
         if (mTheme == null) {
-            if (mThemeResource == 0) {
-                final Context outerContext = getOuterContext();
-                mThemeResource = (outerContext.getApplicationInfo().targetSdkVersion
-                        >= Build.VERSION_CODES.HONEYCOMB)
-                                ? com.android.internal.R.style.Theme_Holo
-                                : com.android.internal.R.style.Theme;
-            }
+            mThemeResource = Resources.selectDefaultTheme(mThemeResource,
+                    getOuterContext().getApplicationInfo().targetSdkVersion);
             mTheme = mResources.newTheme();
             mTheme.applyStyle(mThemeResource, true);
         }
diff --git a/core/java/android/app/IntentService.java b/core/java/android/app/IntentService.java
index 7c2d3a0..57a2695 100644
--- a/core/java/android/app/IntentService.java
+++ b/core/java/android/app/IntentService.java
@@ -113,6 +113,12 @@
         mServiceHandler.sendMessage(msg);
     }
 
+    /**
+     * You should not override this method for your IntentService. Instead,
+     * override {@link #onHandleIntent}, which the system calls when the IntentService
+     * receives a start request.
+     * @see android.app.Service#onStartCommand
+     */
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
         onStart(intent, startId);
@@ -124,6 +130,11 @@
         mServiceLooper.quit();
     }
 
+    /**
+     * Unless you provide binding for your service, you don't need to implement this
+     * method, because the default implementation returns null. 
+     * @see android.app.Service#onBind
+     */
     @Override
     public IBinder onBind(Intent intent) {
         return null;
@@ -135,6 +146,8 @@
      * worker thread that runs independently from other application logic.
      * So, if this code takes a long time, it will hold up other requests to
      * the same IntentService, but it will not hold up anything else.
+     * When all requests have been handled, the IntentService stops itself,
+     * so you should not call {@link #stopSelf}.
      *
      * @param intent The value passed to {@link
      *               android.content.Context#startService(Intent)}.
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index 7730942..9835484 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -214,6 +214,10 @@
         }
     }
 
+    /**
+     * Create the AppWidgetHostView for the given widget.
+     * The AppWidgetHost retains a pointer to the newly-created View.
+     */
     public final AppWidgetHostView createView(Context context, int appWidgetId,
             AppWidgetProviderInfo appWidget) {
         AppWidgetHostView view = onCreateView(context, appWidgetId, appWidget);
@@ -272,6 +276,13 @@
             v.viewDataChanged(viewId);
         }
     }
+
+    /**
+     * Clear the list of Views that have been created by this AppWidgetHost.
+     */
+    protected void clearViews() {
+        mViews.clear();
+    }
 }
 
 
diff --git a/core/java/android/bluetooth/BluetoothDeviceProfileState.java b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
index 21144f2..3280d39 100644
--- a/core/java/android/bluetooth/BluetoothDeviceProfileState.java
+++ b/core/java/android/bluetooth/BluetoothDeviceProfileState.java
@@ -102,7 +102,6 @@
     private BluetoothDevice mDevice;
     private int mHeadsetState = BluetoothProfile.STATE_DISCONNECTED;
     private int mA2dpState = BluetoothProfile.STATE_DISCONNECTED;
-    private int mHidState = BluetoothProfile.STATE_DISCONNECTED;
 
     private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
@@ -140,7 +139,7 @@
                 int newState = intent.getIntExtra(BluetoothInputDevice.EXTRA_INPUT_DEVICE_STATE, 0);
                 int oldState =
                     intent.getIntExtra(BluetoothInputDevice.EXTRA_PREVIOUS_INPUT_DEVICE_STATE, 0);
-                mHidState = newState;
+
                 if (oldState == BluetoothInputDevice.STATE_CONNECTED &&
                     newState == BluetoothInputDevice.STATE_DISCONNECTED) {
                     sendMessage(DISCONNECT_HID_INCOMING);
@@ -286,7 +285,8 @@
                         sendMessage(DISCONNECT_A2DP_OUTGOING);
                         deferMessage(message);
                         break;
-                    } else if (mHidState != BluetoothInputDevice.STATE_DISCONNECTED) {
+                    } else if (mService.getInputDeviceState(mDevice) !=
+                            BluetoothInputDevice.STATE_DISCONNECTED) {
                         sendMessage(DISCONNECT_HID_OUTGOING);
                         deferMessage(message);
                         break;
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index d01a68a..28e1a63 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -324,5 +324,6 @@
     boolean setInstallLocation(int loc);
     int getInstallLocation();
 
-    void setPackageObbPath(String packageName, String path);
+    void setPackageObbPaths(in String packageName, in String[] paths);
+    String[] getPackageObbPaths(in String packageName);
 }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index ac7a95a..47418aa 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2291,15 +2291,30 @@
             String packageName, IPackageMoveObserver observer, int flags);
 
     /**
-     * Sets the Opaque Binary Blob (OBB) file location.
+     * Sets the Opaque Binary Blob (OBB) file path associated with a package
+     * name. The caller must have the
+     * {@link android.Manifest.permission#INSTALL_PACKAGES} permission.
      * <p>
      * NOTE: The existence or format of this file is not currently checked, but
      * it may be in the future.
      * 
      * @param packageName Name of the package with which to associate the .obb
-     *            file
-     * @param path Path on the filesystem to the .obb file
-     * @hide
+     *            file.
+     * @param paths Arrays of paths on the filesystem to the .obb files
+     *            associated with the package.
+     * @see #getPackageObbPaths(String)
      */
-    public abstract void setPackageObbPath(String packageName, String path);
+    public abstract void setPackageObbPaths(String packageName, String[] paths);
+
+    /**
+     * Gets the Opaque Binary Blob (OBB) file path associated with the package.
+     * The caller must be the owner of the package queried or have the
+     * {@link android.Manifest.permission#INSTALL_PACKAGES} permission.
+     * 
+     * @param packageName Name of the package with which to associate the .obb
+     *            file.
+     * @return array of paths to .obb files associated with the package
+     * @see #setPackageObbPaths(String, String[])
+     */
+    public abstract String[] getPackageObbPaths(String packageName);
 }
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index e6fd039..b40a226 100755
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -115,6 +115,23 @@
         return (LongSparseArray<T>) EMPTY_ARRAY;
     }
 
+    /** @hide */
+    public static int selectDefaultTheme(int curTheme, int targetSdkVersion) {
+        return selectSystemTheme(curTheme, targetSdkVersion,
+                com.android.internal.R.style.Theme, com.android.internal.R.style.Theme_Holo);
+    }
+    
+    /** @hide */
+    public static int selectSystemTheme(int curTheme, int targetSdkVersion, int orig, int holo) {
+        if (curTheme != 0) {
+            return curTheme;
+        }
+        if (targetSdkVersion < Build.VERSION_CODES.HONEYCOMB) {
+            return orig;
+        }
+        return holo;
+    }
+    
     /**
      * This exception is thrown by the resource APIs when a requested resource
      * can not be found.
@@ -1459,7 +1476,6 @@
                 }
             }
         }
-        cache.clear();
     }
 
     /**
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 8150493..23b9ad5 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -22,6 +22,7 @@
 import android.app.Dialog;
 import android.content.Context;
 import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Rect;
 import android.os.Bundle;
@@ -220,7 +221,7 @@
     
     InputMethodManager mImm;
     
-    int mTheme = android.R.style.Theme_InputMethod;
+    int mTheme = 0;
     
     LayoutInflater mInflater;
     TypedArray mThemeAttrs;
@@ -556,6 +557,9 @@
     }
     
     @Override public void onCreate() {
+        mTheme = Resources.selectSystemTheme(mTheme,
+                getApplicationInfo().targetSdkVersion,
+                android.R.style.Theme_InputMethod, android.R.style.Theme_Holo_InputMethod);
         super.setTheme(mTheme);
         super.onCreate();
         mImm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index b3a354f..9ecd68c 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -221,6 +221,8 @@
                 if (!TextUtils.equals(apnType, mApnType)) {
                     return;
                 }
+                mNetworkInfo.setSubtype(TelephonyManager.getDefault().getNetworkType(),
+                        TelephonyManager.getDefault().getNetworkTypeName());
                 Phone.DataState state = Enum.valueOf(Phone.DataState.class,
                         intent.getStringExtra(Phone.STATE_KEY));
                 String reason = intent.getStringExtra(Phone.STATE_CHANGE_REASON_KEY);
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index e314fce..0f062cc 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -1632,7 +1632,6 @@
      */
     public static void noteDiskRead() {
         BlockGuard.Policy policy = BlockGuard.getThreadPolicy();
-        Log.d(TAG, "noteDiskRead; policy=" + policy);
         if (!(policy instanceof AndroidBlockGuardPolicy)) {
             // StrictMode not enabled.
             return;
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index 32e609c..dd88838 100644
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -1755,7 +1755,8 @@
                                                 "Need BLUETOOTH_ADMIN permission");
 
         String objectPath = getObjectPathFromAddress(device.getAddress());
-        if (objectPath == null || getConnectedInputDevices().size() == 0) {
+        if (objectPath == null ||
+                getInputDeviceState(device) == BluetoothInputDevice.STATE_DISCONNECTED) {
             return false;
         }
         BluetoothDeviceProfileState state = mDeviceProfileState.get(device.getAddress());
diff --git a/core/java/android/view/ContextThemeWrapper.java b/core/java/android/view/ContextThemeWrapper.java
index be4152b..626f385 100644
--- a/core/java/android/view/ContextThemeWrapper.java
+++ b/core/java/android/view/ContextThemeWrapper.java
@@ -62,12 +62,8 @@
             return mTheme;
         }
 
-        if (mThemeResource == 0) {
-            mThemeResource = (getApplicationInfo().targetSdkVersion
-                    >= Build.VERSION_CODES.HONEYCOMB)
-                            ? com.android.internal.R.style.Theme_Holo
-                            : com.android.internal.R.style.Theme;
-        }
+        mThemeResource = Resources.selectDefaultTheme(mThemeResource,
+                getApplicationInfo().targetSdkVersion);
         initializeTheme();
 
         return mTheme;
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index e81aa98..db2cd50 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -1550,6 +1550,7 @@
     @Override
     public String toString() {
         return "MotionEvent{" + Integer.toHexString(System.identityHashCode(this))
+            + " pointerId=" + getPointerId(0)
             + " action=" + actionToString(mAction)
             + " x=" + getX()
             + " y=" + getY()
@@ -1567,6 +1568,8 @@
             + " edgeFlags=0x" + Integer.toHexString(mEdgeFlags)
             + " device=" + mDeviceId
             + " source=0x" + Integer.toHexString(mSource)
+            + (getPointerCount() > 1 ?
+                " pointerId2=" + getPointerId(1) + " x2=" + getX(2) + " y2=" + getY(2) : "")
             + "}";
     }
 
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 45c35f0..63a3ff0 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -58,6 +58,7 @@
 import android.util.Pools;
 import android.util.SparseArray;
 import android.view.ContextMenu.ContextMenuInfo;
+import android.view.View.MeasureSpec;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityEventSource;
 import android.view.accessibility.AccessibilityManager;
@@ -3260,6 +3261,9 @@
      * {@inheritDoc}
      */
     public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
+        if (!isShown()) {
+            return;
+        }
         event.setClassName(getClass().getName());
         event.setPackageName(getContext().getPackageName());
         event.setEnabled(isEnabled());
@@ -7576,6 +7580,9 @@
             mHardwareLayer.destroy();
             mHardwareLayer = null;
         }
+        mAttachInfo.mHandler.removeMessages(AttachInfo.INVALIDATE_MSG, this);
+        mAttachInfo.mHandler.removeMessages(AttachInfo.INVALIDATE_RECT_MSG, this);
+        mCurrentAnimation = null;
     }
 
     /**
@@ -7822,6 +7829,9 @@
      *
      * <p>Note: if this view's parent addStateFromChildren property is enabled and this
      * property is enabled, an exception will be thrown.</p>
+     * 
+     * <p>Note: if the child view uses and updates additionnal states which are unknown to the
+     * parent, these states should not be affected by this method.</p>
      *
      * @param enabled True to enable duplication of the parent's drawable state, false
      *                to disable it.
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 0186f21..f6b6778 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -44,6 +44,7 @@
 import android.view.animation.Transformation;
 
 import java.util.ArrayList;
+import java.util.HashSet;
 
 /**
  * <p>
@@ -111,6 +112,10 @@
     // View currently under an ongoing drag
     private View mCurrentDragView;
 
+    // Metadata about the ongoing drag
+    private DragEvent mCurrentDrag;
+    private HashSet<View> mDragNotifiedChildren;
+
     // Does this group have a child that can accept the current drag payload?
     private boolean mChildAcceptsDrag;
 
@@ -803,6 +808,13 @@
                 }
             }
         }
+
+        // in all cases, for drags
+        if (mCurrentDrag != null) {
+            if (visibility == VISIBLE) {
+                notifyChildOfDrag(child);
+            }
+        }
     }
 
     /**
@@ -894,6 +906,14 @@
             // clear state to recalculate which views we drag over
             mCurrentDragView = null;
 
+            // Set up our tracking of drag-started notifications
+            mCurrentDrag = DragEvent.obtain(event);
+            if (mDragNotifiedChildren == null) {
+                mDragNotifiedChildren = new HashSet<View>();
+            } else {
+                mDragNotifiedChildren.clear();
+            }
+
             // Now dispatch down to our children, caching the responses
             mChildAcceptsDrag = false;
             final int count = mChildrenCount;
@@ -901,8 +921,7 @@
             for (int i = 0; i < count; i++) {
                 final View child = children[i];
                 if (child.getVisibility() == VISIBLE) {
-                    final boolean handled = children[i].dispatchDragEvent(event);
-                    children[i].mCanAcceptDrop = handled;
+                    final boolean handled = notifyChildOfDrag(children[i]);
                     if (handled) {
                         mChildAcceptsDrag = true;
                     }
@@ -916,15 +935,16 @@
         } break;
 
         case DragEvent.ACTION_DRAG_ENDED: {
-            // Notify all of our children that the drag is over
-            final int count = mChildrenCount;
-            final View[] children = mChildren;
-            for (int i = 0; i < count; i++) {
-                final View child = children[i];
-                if (child.getVisibility() == VISIBLE) {
-                    child.dispatchDragEvent(event);
-                }
+            // If a child was notified about an ongoing drag, it's told that it's over
+            for (View child : mDragNotifiedChildren) {
+                child.dispatchDragEvent(event);
             }
+
+            // Release the bookkeeping now that the drag lifecycle has ended
+            mDragNotifiedChildren.clear();
+            mCurrentDrag.recycle();
+            mCurrentDrag = null;
+
             // We consider drag-ended to have been handled if one of our children
             // had offered to handle the drag.
             if (mChildAcceptsDrag) {
@@ -1036,6 +1056,18 @@
         return null;
     }
 
+    boolean notifyChildOfDrag(View child) {
+        if (ViewDebug.DEBUG_DRAG) {
+            Log.d(View.VIEW_LOG_TAG, "Sending drag-started to view: " + child);
+        }
+
+        if (! mDragNotifiedChildren.contains(child)) {
+            mDragNotifiedChildren.add(child);
+            child.mCanAcceptDrop = child.dispatchDragEvent(mCurrentDrag);
+        }
+        return child.mCanAcceptDrop;
+    }
+
     /**
      * {@inheritDoc}
      */
@@ -1834,6 +1866,13 @@
         // In case view is detached while transition is running
         mLayoutSuppressed = false;
 
+        // Tear down our drag tracking
+        mDragNotifiedChildren = null;
+        if (mCurrentDrag != null) {
+            mCurrentDrag.recycle();
+            mCurrentDrag = null;
+        }
+
         final int count = mChildrenCount;
         final View[] children = mChildren;
         for (int i = 0; i < count; i++) {
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index d480bbc..ad9e6863 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -486,16 +486,16 @@
         mAttachInfo.mHardwareAccelerated = false;
         mAttachInfo.mHardwareAccelerationRequested = false;
 
-        // Don't enable hardware acceleration when we're not on the main thread
-        if (Looper.getMainLooper() != Looper.myLooper()) {
-            Log.w(HardwareRenderer.LOG_TAG, "Attempting to initialize hardware acceleration " 
-                    + "outside of the main thread, aborting");
-            return;
-        }
-
         // Try to enable hardware acceleration if requested
         if (attrs != null &&
                 (attrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0) {
+            // Don't enable hardware acceleration when we're not on the main thread
+            if (Looper.getMainLooper() != Looper.myLooper()) {
+                Log.w(HardwareRenderer.LOG_TAG, "Attempting to initialize hardware acceleration "
+                        + "outside of the main thread, aborting");
+                return;
+            }
+
             // Only enable hardware acceleration if we are not in the system process
             // The window manager creates ViewRoots to display animated preview windows
             // of launching apps and we don't want those to be hardware accelerated
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index cb0a2a9..e8d67da 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -23,6 +23,9 @@
 import android.os.LocalPowerManager;
 import android.view.animation.Animation;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
 /**
  * This interface supplies all UI-specific behavior of the window manager.  An
  * instance of it is created by the window manager when it starts up, and allows
@@ -817,4 +820,15 @@
      *                 {@link Surface#ROTATION_180}, {@link Surface#ROTATION_270}. 
      */
     public void setUserRotationMode(int mode, int rotation);
+
+    /**
+     * Print the WindowManagerPolicy's state into the given stream.
+     *
+     * @param prefix Text to print at the front of each line.
+     * @param fd The raw file descriptor that the dump is being sent to.
+     * @param writer The PrintWriter to which you should dump your state.  This will be
+     * closed for you after you return.
+     * @param args additional arguments to the dump request.
+     */
+    public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args);
 }
diff --git a/core/java/android/view/WindowOrientationListener.java b/core/java/android/view/WindowOrientationListener.java
index 2a76e33..6095a64 100755
--- a/core/java/android/view/WindowOrientationListener.java
+++ b/core/java/android/view/WindowOrientationListener.java
@@ -234,6 +234,14 @@
         // high time constant.
         private static final float MAX_DEVIATION_FROM_GRAVITY = 1.5f;
 
+        // Minimum acceleration considered, in m/s^2. Below this threshold sensor noise will have
+        // significant impact on the calculations and in case of the vector (0, 0, 0) there is no
+        // defined rotation or tilt at all. Low or zero readings can happen when space travelling
+        // or free falling, but more commonly when shaking or getting bad readings from the sensor.
+        // The accelerometer is turned off when not used and polling it too soon after it is
+        // turned on may result in (0, 0, 0).
+        private static final float MIN_ABS_ACCELERATION = 1.5f;
+
         // Actual sampling period corresponding to SensorManager.SENSOR_DELAY_NORMAL.  There's no
         // way to get this information from SensorManager.
         // Note the actual period is generally 3-30ms larger than this depending on the device, but
@@ -347,6 +355,9 @@
             float deviation = Math.abs(magnitude - SensorManager.STANDARD_GRAVITY);
 
             handleAccelerationDistrust(deviation);
+            if (magnitude < MIN_ABS_ACCELERATION) {
+                return; // Ignore tilt and orientation when (0, 0, 0) or low reading
+            }
 
             // only filter tilt when we're accelerating
             float alpha = 1;
diff --git a/core/java/android/webkit/CacheManager.java b/core/java/android/webkit/CacheManager.java
index e46daad..6073f7a 100644
--- a/core/java/android/webkit/CacheManager.java
+++ b/core/java/android/webkit/CacheManager.java
@@ -191,7 +191,14 @@
      */
     static void init(Context context) {
         if (JniUtil.useChromiumHttpStack()) {
-            // TODO: Need to init mBaseDir.
+            // This isn't actually where the real cache lives, but where we put files for the
+            // purpose of getCacheFile().
+            mBaseDir = new File(context.getCacheDir(), "webviewCacheChromiumStaging");
+            if (!mBaseDir.exists()) {
+                mBaseDir.mkdirs();
+            } else {
+                // TODO: Should we clear out old files?
+            }
             return;
         }
 
@@ -343,8 +350,8 @@
     /**
      * Given a URL, returns the corresponding CacheResult if it exists, or null otherwise.
      *
-     * The output stream of the CacheEntry object is initialized and opened and should be closed by
-     * the caller when access to the undelying file is no longer required.
+     * The input stream of the CacheEntry object is initialized and opened and should be closed by
+     * the caller when access to the underlying file is no longer required.
      * If a non-zero value is provided for the headers map, and the cache entry needs validation,
      * HEADER_KEY_IFNONEMATCH or HEADER_KEY_IFMODIFIEDSINCE will be set in headers.
      *
@@ -365,8 +372,24 @@
         }
 
         if (JniUtil.useChromiumHttpStack()) {
-            // TODO: Implement this.
-            return null;
+            CacheResult result = nativeGetCacheResult(url);
+            if (result == null) {
+                return null;
+            }
+            // A temporary local file will have been created native side and localPath set
+            // appropriately.
+            File src = new File(mBaseDir, result.localPath);
+            try {
+                // Open the file here so that even if it is deleted, the content
+                // is still readable by the caller until close() is called.
+                result.inStream = new FileInputStream(src);
+            } catch (FileNotFoundException e) {
+                Log.v(LOGTAG, "getCacheFile(): Failed to open file: " + e);
+                // TODO: The files in the cache directory can be removed by the
+                // system. If it is gone, what should we do?
+                return null;
+            }
+            return result;
         }
 
         String databaseKey = getDatabaseKey(url, postIdentifier);
@@ -437,7 +460,7 @@
     public static CacheResult createCacheFile(String url, int statusCode,
             Headers headers, String mimeType, boolean forceCache) {
         if (JniUtil.useChromiumHttpStack()) {
-            // TODO: Implement this.
+            // This method is public but hidden. We break functionality.
             return null;
         }
 
@@ -522,8 +545,16 @@
         }
 
         if (JniUtil.useChromiumHttpStack()) {
-            // TODO: Implement this.
-            return;
+            // This method is exposed in the public API but the API provides no way to obtain a
+            // new CacheResult object with a non-null output stream ...
+            // - CacheResult objects returned by getCacheFile() have a null output stream.
+            // - new CacheResult objects have a null output stream and no setter is provided.
+            // Since for the Android HTTP stack this method throws a null pointer exception in this
+            // case, this method is effectively useless from the point of view of the public API.
+
+            // We should already have thrown an exception above, to maintain 'backward
+            // compatibility' with the Android HTTP stack.
+            assert false;
         }
 
         if (!cacheRet.outFile.exists()) {
@@ -917,4 +948,6 @@
 
         return ret;
     }
+
+    private static native CacheResult nativeGetCacheResult(String url);
 }
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index b893af8..eddfffe 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -5471,6 +5471,8 @@
                     if (shouldForwardTouchEvent()) {
                         TouchEventData ted = new TouchEventData();
                         ted.mAction = action;
+                        ted.mIds = new int[1];
+                        ted.mIds[0] = ev.getPointerId(0);
                         ted.mPoints = new Point[1];
                         ted.mPoints[0] = new Point(contentX, contentY);
                         ted.mMetaState = ev.getMetaState();
@@ -5513,6 +5515,8 @@
                         || eventTime - mLastSentTouchTime > mCurrentTouchInterval)) {
                     TouchEventData ted = new TouchEventData();
                     ted.mAction = action;
+                    ted.mIds = new int[1];
+                    ted.mIds[0] = ev.getPointerId(0);
                     ted.mPoints = new Point[1];
                     ted.mPoints[0] = new Point(contentX, contentY);
                     ted.mMetaState = ev.getMetaState();
@@ -5582,6 +5586,24 @@
                         break;
                     }
 
+                    // Only lock dragging to one axis if we don't have a scale in progress.
+                    // Scaling implies free-roaming movement. Note this is only ever a question
+                    // if mZoomManager.supportsPanDuringZoom() is true.
+                    final ScaleGestureDetector detector =
+                      mZoomManager.getMultiTouchGestureDetector();
+                    if (detector == null || !detector.isInProgress()) {
+                        // if it starts nearly horizontal or vertical, enforce it
+                        int ax = Math.abs(deltaX);
+                        int ay = Math.abs(deltaY);
+                        if (ax > MAX_SLOPE_FOR_DIAG * ay) {
+                            mSnapScrollMode = SNAP_X;
+                            mSnapPositive = deltaX > 0;
+                        } else if (ay > MAX_SLOPE_FOR_DIAG * ax) {
+                            mSnapScrollMode = SNAP_Y;
+                            mSnapPositive = deltaY > 0;
+                        }
+                    }
+
                     mTouchMode = TOUCH_DRAG_MODE;
                     mLastTouchX = x;
                     mLastTouchY = y;
@@ -5682,6 +5704,8 @@
                 // pass the touch events from UI thread to WebCore thread
                 if (shouldForwardTouchEvent()) {
                     TouchEventData ted = new TouchEventData();
+                    ted.mIds = new int[1];
+                    ted.mIds[0] = ev.getPointerId(0);
                     ted.mAction = action;
                     ted.mPoints = new Point[1];
                     ted.mPoints[0] = new Point(contentX, contentY);
@@ -5699,6 +5723,8 @@
                         mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
                         if (inFullScreenMode() || mDeferTouchProcess) {
                             TouchEventData ted = new TouchEventData();
+                            ted.mIds = new int[1];
+                            ted.mIds[0] = ev.getPointerId(0);
                             ted.mAction = WebViewCore.ACTION_DOUBLETAP;
                             ted.mPoints = new Point[1];
                             ted.mPoints[0] = new Point(contentX, contentY);
@@ -5832,8 +5858,10 @@
         TouchEventData ted = new TouchEventData();
         ted.mAction = ev.getAction() & MotionEvent.ACTION_MASK;
         final int count = ev.getPointerCount();
+        ted.mIds = new int[count];
         ted.mPoints = new Point[count];
         for (int c = 0; c < count; c++) {
+            ted.mIds[c] = ev.getPointerId(c);
             int x = viewToContentX((int) ev.getX(c) + mScrollX);
             int y = viewToContentY((int) ev.getY(c) + mScrollY);
             ted.mPoints[c] = new Point(x, y);
@@ -5927,6 +5955,8 @@
                 mWebViewCore.removeMessages(EventHub.TOUCH_EVENT);
             }
             TouchEventData ted = new TouchEventData();
+            ted.mIds = new int[1];
+            ted.mIds[0] = 0;
             ted.mPoints = new Point[1];
             ted.mPoints[0] = new Point(x, y);
             ted.mAction = MotionEvent.ACTION_CANCEL;
@@ -7054,6 +7084,8 @@
                     if (inFullScreenMode() || mDeferTouchProcess) {
                         TouchEventData ted = new TouchEventData();
                         ted.mAction = WebViewCore.ACTION_LONGPRESS;
+                        ted.mIds = new int[1];
+                        ted.mIds[0] = 0;
                         ted.mPoints = new Point[1];
                         ted.mPoints[0] = new Point(viewToContentX((int) mLastTouchX + mScrollX),
                                                    viewToContentY((int) mLastTouchY + mScrollY));
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 2ea20ee..c56f252 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -562,8 +562,8 @@
     private native void nativeTouchUp(int touchGeneration,
             int framePtr, int nodePtr, int x, int y);
 
-    private native boolean nativeHandleTouchEvent(int action, int[] x, int[] y,
-            int count, int metaState);
+    private native boolean nativeHandleTouchEvent(int action, int[] idArray,
+            int[] xArray, int[] yArray, int count, int metaState);
 
     private native void nativeUpdateFrameCache();
 
@@ -828,6 +828,7 @@
 
     static class TouchEventData {
         int mAction;
+        int[] mIds;  // Ids of the touch points
         Point[] mPoints;
         int mMetaState;
         boolean mReprocess;
@@ -1336,8 +1337,8 @@
                                     mWebView.mPrivateHandler,
                                     WebView.PREVENT_TOUCH_ID,
                                     ted.mAction,
-                                    nativeHandleTouchEvent(ted.mAction, xArray,
-                                            yArray, count, ted.mMetaState) ? 1 : 0,
+                                    nativeHandleTouchEvent(ted.mAction, ted.mIds,
+                                        xArray, yArray, count, ted.mMetaState) ? 1 : 0,
                                     ted.mReprocess ? ted : null).sendToTarget();
                             break;
                         }
diff --git a/core/java/android/webkit/WebViewFragment.java b/core/java/android/webkit/WebViewFragment.java
new file mode 100644
index 0000000..466f174
--- /dev/null
+++ b/core/java/android/webkit/WebViewFragment.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.webkit.WebView;
+
+/**
+ * A fragment that displays a WebView.
+ * <p>
+ * The WebView is automically paused or resumed when the Fragment is paused or resumed.
+ */
+public class WebViewFragment extends Fragment {
+    private WebView mWebView;
+
+    public WebViewFragment() {
+    }
+
+    /**
+     * Called to instantiate the view. Creates and returns the WebView.
+     */
+    @Override
+    public View onCreateView(LayoutInflater inflater, ViewGroup container,
+            Bundle savedInstanceState) {
+        mWebView = new WebView(getActivity());
+        return mWebView;
+    }
+
+    /**
+     * Called when the fragment is visible to the user and actively running. Resumes the WebView.
+     */
+    @Override
+    public void onPause() {
+        super.onPause();
+        mWebView.onPause();
+    }
+
+    /**
+     * Called when the fragment is no longer resumed. Pauses the WebView.
+     */
+    @Override
+    public void onResume() {
+        mWebView.onResume();
+        super.onResume();
+    }
+
+    /**
+     * Called when the view has been detached from the fragment. Destroys the WebView.
+     */
+    @Override
+    public void onDestroyView() {
+        mWebView.destroy();
+        mWebView = null;
+        super.onDestroyView();
+    }
+
+    /**
+     * Gets the WebView.
+     */
+    public WebView getWebView() {
+        return mWebView;
+    }
+}
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 2e38743..7631df4 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -4106,8 +4106,7 @@
         final int topLimit = getPaddingTop();
         final int bottomLimit = getHeight() - getPaddingBottom();
 
-        if (distance == 0 ||
-                firstPos == INVALID_POSITION ||
+        if (distance == 0 || mItemCount == 0 || childCount == 0 ||
                 (firstPos == 0 && getChildAt(0).getTop() == topLimit && distance < 0) ||
                 (lastPos == mItemCount - 1 &&
                         getChildAt(childCount - 1).getBottom() == bottomLimit && distance > 0)) {
diff --git a/core/java/android/widget/AdapterViewAnimator.java b/core/java/android/widget/AdapterViewAnimator.java
index ec8e93c..1b39371 100644
--- a/core/java/android/widget/AdapterViewAnimator.java
+++ b/core/java/android/widget/AdapterViewAnimator.java
@@ -986,4 +986,10 @@
 
     public void willBeAdvancedByHost() {
     }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        mAdapter = null;
+        super.onDetachedFromWindow();
+    }
 }
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 5b143fe..ef4e4e0 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -1004,9 +1004,11 @@
 
     @Override
     protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
         if (mIndeterminate) {
             stopAnimation();
         }
+        // This should come after stopAnimation(), otherwise an invalidate message remains in the
+        // queue, which can prevent the entire view hierarchy from being GC'ed during a rotation
+        super.onDetachedFromWindow();
     }
 }
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index a7bff62..df1f4bf 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -152,6 +152,7 @@
             if (callback != null) {
                 callback.onRemoteAdapterDisconnected();
             }
+            adapter.mCache.reset();
         }
 
         public IRemoteViewsFactory getRemoteViewsFactory() {
@@ -657,11 +658,9 @@
             try {
                 remoteViews = factory.getViewAt(position);
                 itemId = factory.getItemId(position);
-            } catch (Exception e) {
-                // Print the error
-                Log.e(TAG, "Error in updateRemoteViews(" + position + "): " +
-                        e.getMessage());
-                e.printStackTrace();
+            } catch (Throwable t) {
+                Log.e(TAG, "Error in updateRemoteViews(" + position + "): " + t.getMessage());
+                t.printStackTrace();
 
                 // Return early to prevent additional work in re-centering the view cache, and
                 // swapping from the loading view
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 3bf5af3..2c96056 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -217,6 +217,10 @@
         if (maxWidth != -1) {
             setMaxWidth(maxWidth);
         }
+        CharSequence queryHint = a.getText(R.styleable.SearchView_queryHint);
+        if (!TextUtils.isEmpty(queryHint)) {
+            setQueryHint(queryHint);
+        }
         a.recycle();
 
         // Save voice intent for later queries/launching
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index b892fe2..623cd41 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -4135,9 +4135,12 @@
 
     @Override
     protected int[] onCreateDrawableState(int extraSpace) {
-        final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
+        final int[] drawableState;
 
-        if (!mSingleLine) {
+        if (mSingleLine) {
+            drawableState = super.onCreateDrawableState(extraSpace);
+        } else {
+            drawableState = super.onCreateDrawableState(extraSpace + 1);
             mergeDrawableStates(drawableState, MULTILINE_STATE_SET);
         }
 
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index f5c0124..4ee3083 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -681,12 +681,12 @@
 
         @Override
         public void setTitle(int resId) {
-            setTitle(mActivity.getString(resId));
+            setTitle(mContext.getResources().getString(resId));
         }
 
         @Override
         public void setSubtitle(int resId) {
-            setSubtitle(mActivity.getString(resId));
+            setSubtitle(mContext.getResources().getString(resId));
         }
 
         @Override
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItemView.java b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
index d5f69ba..3325df6 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
@@ -66,7 +66,7 @@
         mItemData = itemData;
 
         setIcon(itemData.getIcon());
-        setTitle(itemData.getTitle()); // Title only takes effect if there is no icon
+        setTitle(itemData.getTitleForItemView(this)); // Title only takes effect if there is no icon
         setId(itemData.getItemId());
 
         setVisibility(itemData.isVisible() ? View.VISIBLE : View.GONE);
@@ -91,7 +91,7 @@
     }
 
     public boolean prefersCondensedTitle() {
-        return false;
+        return true;
     }
 
     public void setCheckable(boolean checkable) {
@@ -106,10 +106,11 @@
         mImageButton.setImageDrawable(icon);
         if (icon != null) {
             mImageButton.setVisibility(VISIBLE);
-            mTextButton.setVisibility(GONE);
         } else {
             mImageButton.setVisibility(GONE);
         }
+
+        mTextButton.setVisibility(icon == null || mItemData.showsTextAsAction() ? VISIBLE : GONE);
     }
     
     public boolean hasText() {
diff --git a/core/java/com/android/internal/view/menu/ActionMenuView.java b/core/java/com/android/internal/view/menu/ActionMenuView.java
index 463902f..8e491e9 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuView.java
@@ -20,9 +20,9 @@
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
+import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.Gravity;
-import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewParent;
@@ -186,10 +186,14 @@
         
         boolean needsDivider = false;
         for (int i = 0; i < itemCount; i++) {
+            final MenuItemImpl itemData = itemsToShow.get(i);
+            boolean hasDivider = false;
+
             if (needsDivider) {
                 addView(makeDividerView(), makeDividerLayoutParams());
+                hasDivider = true;
             }
-            final MenuItemImpl itemData = itemsToShow.get(i);
+
             View actionView = itemData.getActionView();
 
             if (actionView != null) {
@@ -199,14 +203,22 @@
                 }
                 addView(actionView, makeActionViewLayoutParams(actionView));
             } else {
-                needsDivider = addItemView(i == 0 || !needsDivider,
-                        (ActionMenuItemView) itemData.getItemView(
-                                MenuBuilder.TYPE_ACTION_BUTTON, this));
+                ActionMenuItemView view = (ActionMenuItemView) itemData.getItemView(
+                        MenuBuilder.TYPE_ACTION_BUTTON, this);
+                view.setItemInvoker(this);
+                if (i > 0 && !hasDivider && view.hasText() && itemData.getIcon() == null) {
+                    addView(makeDividerView(), makeDividerLayoutParams());
+                }
+                addView(view);
+                needsDivider = view.hasText();
             }
         }
 
         if (reserveOverflow) {
             if (mMenu.getNonActionItems(true).size() > 0) {
+                if (itemCount > 0) {
+                    addView(makeDividerView(), makeDividerLayoutParams());
+                }
                 OverflowMenuButton button = new OverflowMenuButton(mContext);
                 addView(button);
                 mOverflowButton = button;
diff --git a/core/java/com/android/internal/view/menu/ListMenuItemView.java b/core/java/com/android/internal/view/menu/ListMenuItemView.java
index e155875..02584b6 100644
--- a/core/java/com/android/internal/view/menu/ListMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ListMenuItemView.java
@@ -44,6 +44,7 @@
     private Drawable mBackground;
     private int mTextAppearance;
     private Context mTextAppearanceContext;
+    private boolean mPreserveIconSpacing;
     
     private int mMenuType;
     
@@ -57,6 +58,8 @@
         mBackground = a.getDrawable(com.android.internal.R.styleable.MenuView_itemBackground);
         mTextAppearance = a.getResourceId(com.android.internal.R.styleable.
                                           MenuView_itemTextAppearance, -1);
+        mPreserveIconSpacing = a.getBoolean(
+                com.android.internal.R.styleable.MenuView_preserveIconSpacing, false);
         mTextAppearanceContext = context;
         
         a.recycle();
@@ -184,8 +187,8 @@
     }
     
     public void setIcon(Drawable icon) {
-        
-        if (!mItemData.shouldShowIcon(mMenuType)) {
+        final boolean showIcon = mItemData.shouldShowIcon(mMenuType);
+        if (!showIcon && !mPreserveIconSpacing) {
             return;
         }
         
@@ -197,8 +200,8 @@
             insertIconView();
         }
         
-        if (icon != null) {
-            mIconView.setImageDrawable(icon);
+        if (icon != null || mPreserveIconSpacing) {
+            mIconView.setImageDrawable(showIcon ? icon : null);
 
             if (mIconView.getVisibility() != VISIBLE) {
                 mIconView.setVisibility(VISIBLE);
diff --git a/core/java/com/android/internal/view/menu/MenuItemImpl.java b/core/java/com/android/internal/view/menu/MenuItemImpl.java
index e1aa385..6fbae94 100644
--- a/core/java/com/android/internal/view/menu/MenuItemImpl.java
+++ b/core/java/com/android/internal/view/menu/MenuItemImpl.java
@@ -644,7 +644,6 @@
     public boolean shouldShowIcon(int menuType) {
         return menuType == MenuBuilder.TYPE_ICON ||
                 menuType == MenuBuilder.TYPE_ACTION_BUTTON ||
-                menuType == MenuBuilder.TYPE_POPUP ||
                 mMenu.getOptionalIconsVisible();
     }
     
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 1d9276a..297dde7 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -437,7 +437,7 @@
                     mListNavLayout = new LinearLayout(mContext, null,
                             com.android.internal.R.attr.actionBarTabBarStyle);
                     LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
-                            LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+                            LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
                     params.gravity = Gravity.CENTER;
                     mListNavLayout.addView(mSpinner, params);
                 }
diff --git a/core/res/res/drawable-hdpi/ic_btn_round_more_disabled.png b/core/res/res/drawable-hdpi/ic_btn_round_more_disabled.png
old mode 100644
new mode 100755
index 0125944..3f1176f
--- a/core/res/res/drawable-hdpi/ic_btn_round_more_disabled.png
+++ b/core/res/res/drawable-hdpi/ic_btn_round_more_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_btn_round_more_normal.png b/core/res/res/drawable-hdpi/ic_btn_round_more_normal.png
old mode 100644
new mode 100755
index 33d7f89..8abda4d
--- a/core/res/res/drawable-hdpi/ic_btn_round_more_normal.png
+++ b/core/res/res/drawable-hdpi/ic_btn_round_more_normal.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_chat.png b/core/res/res/drawable-hdpi/stat_notify_chat.png
index 71ea8de..95b2700 100644
--- a/core/res/res/drawable-hdpi/stat_notify_chat.png
+++ b/core/res/res/drawable-hdpi/stat_notify_chat.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_email_generic.png b/core/res/res/drawable-hdpi/stat_notify_email_generic.png
index bc5fcab..f222872 100644
--- a/core/res/res/drawable-hdpi/stat_notify_email_generic.png
+++ b/core/res/res/drawable-hdpi/stat_notify_email_generic.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/stat_notify_gmail.png b/core/res/res/drawable-hdpi/stat_notify_gmail.png
index ea8beae..2d5686d 100644
--- a/core/res/res/drawable-hdpi/stat_notify_gmail.png
+++ b/core/res/res/drawable-hdpi/stat_notify_gmail.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_btn_round_more_disabled.png b/core/res/res/drawable-mdpi/ic_btn_round_more_disabled.png
index 1ab98c9..428edf2 100644
--- a/core/res/res/drawable-mdpi/ic_btn_round_more_disabled.png
+++ b/core/res/res/drawable-mdpi/ic_btn_round_more_disabled.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_btn_round_more_normal.png b/core/res/res/drawable-mdpi/ic_btn_round_more_normal.png
index ebdc55c..c2ecb01 100644
--- a/core/res/res/drawable-mdpi/ic_btn_round_more_normal.png
+++ b/core/res/res/drawable-mdpi/ic_btn_round_more_normal.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_arrow.png b/core/res/res/drawable-mdpi/pointer_arrow.png
new file mode 100644
index 0000000..e01129c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_arrow.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/pointer_arrow_icon.xml b/core/res/res/drawable-mdpi/pointer_arrow_icon.xml
new file mode 100644
index 0000000..2f5676f
--- /dev/null
+++ b/core/res/res/drawable-mdpi/pointer_arrow_icon.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
+    android:bitmap="@drawable/pointer_arrow"
+    android:hotSpotX="6"
+    android:hotSpotY="6" />
diff --git a/core/res/res/drawable-mdpi/pointericon_default.xml b/core/res/res/drawable-mdpi/pointericon_default.xml
deleted file mode 100644
index b1357b6..0000000
--- a/core/res/res/drawable-mdpi/pointericon_default.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<pointer-icon xmlns:android="http://schemas.android.com/apk/res/android"
-    android:bitmap="@drawable/pointericon_default_bitmap"
-    android:hotSpotX="2"
-    android:hotSpotY="2" />
diff --git a/core/res/res/drawable-mdpi/pointericon_default_bitmap.png b/core/res/res/drawable-mdpi/pointericon_default_bitmap.png
deleted file mode 100644
index 7e073a3..0000000
--- a/core/res/res/drawable-mdpi/pointericon_default_bitmap.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_chat.png b/core/res/res/drawable-mdpi/stat_notify_chat.png
index 8cf02cc..f199fce 100644
--- a/core/res/res/drawable-mdpi/stat_notify_chat.png
+++ b/core/res/res/drawable-mdpi/stat_notify_chat.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_email_generic.png b/core/res/res/drawable-mdpi/stat_notify_email_generic.png
index 5b866bf..536e8ec 100644
--- a/core/res/res/drawable-mdpi/stat_notify_email_generic.png
+++ b/core/res/res/drawable-mdpi/stat_notify_email_generic.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_notify_gmail.png b/core/res/res/drawable-mdpi/stat_notify_gmail.png
index 907306d..89fe3cd 100644
--- a/core/res/res/drawable-mdpi/stat_notify_gmail.png
+++ b/core/res/res/drawable-mdpi/stat_notify_gmail.png
Binary files differ
diff --git a/core/res/res/layout/action_menu_item_layout.xml b/core/res/res/layout/action_menu_item_layout.xml
index e502b1e..e001894 100644
--- a/core/res/res/layout/action_menu_item_layout.xml
+++ b/core/res/res/layout/action_menu_item_layout.xml
@@ -20,10 +20,11 @@
     android:layout_gravity="center"
     android:addStatesFromChildren="true"
     android:background="?attr/selectableItemBackground"
-    android:minWidth="64dip"
-    android:minHeight="?attr/actionBarSize"
+    android:gravity="center"
     android:paddingLeft="12dip"
-    android:paddingRight="12dip">
+    android:paddingRight="12dip"
+    android:minWidth="64dip"
+    android:minHeight="?attr/actionBarSize">
     <ImageButton android:id="@+id/imageButton"
                  android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
diff --git a/core/res/res/layout/list_menu_item_icon.xml b/core/res/res/layout/list_menu_item_icon.xml
index 2be9fab..6ff14dd 100644
--- a/core/res/res/layout/list_menu_item_icon.xml
+++ b/core/res/res/layout/list_menu_item_icon.xml
@@ -19,6 +19,6 @@
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_gravity="center_vertical"
-    android:layout_marginLeft="2dip"
+    android:layout_marginRight="8dip"
     android:duplicateParentState="true" />
 
diff --git a/core/res/res/layout/popup_menu_item_layout.xml b/core/res/res/layout/popup_menu_item_layout.xml
index 2bbb4d0..d22f74a 100644
--- a/core/res/res/layout/popup_menu_item_layout.xml
+++ b/core/res/res/layout/popup_menu_item_layout.xml
@@ -16,7 +16,8 @@
 
 <com.android.internal.view.menu.ListMenuItemView xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="?android:attr/listPreferredItemHeight"
+    android:layout_height="48dip"
+    android:minWidth="196dip"
     android:paddingLeft="16dip"
     android:paddingRight="16dip">
     
@@ -28,8 +29,6 @@
         android:layout_weight="1"
         android:layout_height="wrap_content"
         android:layout_gravity="center_vertical"
-        android:layout_marginLeft="6dip"
-        android:layout_marginRight="6dip"
         android:duplicateParentState="true">
         
         <TextView 
diff --git a/core/res/res/values-es-rUS-xlarge/strings.xml b/core/res/res/values-es-rUS-xlarge/strings.xml
index 4743ac5..b1409ba 100644
--- a/core/res/res/values-es-rUS-xlarge/strings.xml
+++ b/core/res/res/values-es-rUS-xlarge/strings.xml
@@ -303,6 +303,10 @@
     <!-- XL -->
     <string name="status_bar_notification_info_overflow" msgid="1081154808901480710">"100+"</string>
     <!-- XL -->
+    <string name="permlab_accessMtp" msgid="2385215229145694622">"implementar protocolo MTP"</string>
+    <!-- XL -->
+    <string name="permdesc_accessMtp" msgid="4707854877711083465">"Permite acceso al driver kernel MTP para implementar el protocolo MTP USB."</string>
+    <!-- XL -->
     <string name="permlab_mediaStorageWrite" product="default" msgid="5585262071354704256">"modificar/eliminar los contenidos del almacenamientos de medios internos"</string>
     <!-- XL -->
     <string name="permdesc_mediaStorageWrite" product="default" msgid="2372999661142345443">"Permite que una aplicación modifique los contenidos del almacenamiento interno de medios."</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 3a3ca36..02855b5 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2349,6 +2349,8 @@
         <attr name="windowAnimationStyle" />
         <!-- Default disabled icon alpha for each menu item that shows an icon. -->
         <attr name="itemIconDisabledAlpha" format="float" />
+        <!-- Whether space should be reserved in layout when an icon is missing. -->
+        <attr name="preserveIconSpacing" format="boolean" />
     </declare-styleable>
     <declare-styleable name="IconMenuView">
         <!-- Defines the height of each row. -->
@@ -4664,6 +4666,8 @@
         <attr name="iconifiedByDefault" format="boolean"/>
         <!-- An optional maximum width of the SearchView. -->
         <attr name="maxWidth" />
+        <!-- An optional query hint string to be displayed in the empty query field. -->
+        <attr name="queryHint" format="string" />
     </declare-styleable>
 
     <declare-styleable name="ActionBar_LayoutParams">
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 6d79569..9b88b01 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1424,6 +1424,7 @@
   <public type="attr" name="alertDialogIcon" />
   <public type="attr" name="windowMinWidthMajor" />
   <public type="attr" name="windowMinWidthMinor" />
+  <public type="attr" name="queryHint" />
 
   <!-- A simple fade-in animation. -->
   <public type="animator" name="fade_in" id="0x010b0000" />
@@ -1513,6 +1514,7 @@
   <public type="style" name="Theme.Holo.Light.Panel" />
   <public type="style" name="Theme.Holo.Wallpaper" />
   <public type="style" name="Theme.Holo.Wallpaper.NoTitleBar" />
+  <public type="style" name="Theme.Holo.InputMethod" />
 
   <public type="style" name="TextAppearance.Widget.PopupMenu.Large" />
   <public type="style" name="TextAppearance.Widget.PopupMenu.Small" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index f346bac..2658b53 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2403,6 +2403,8 @@
 
     <!-- Title of the pop-up dialog in which the user switches input method components. -->
     <string name="select_input_method">Select input method</string>
+    <!-- Title of a button to open the settings for input methods [CHAR LIMIT=30] -->
+    <string name="configure_input_methods">Configure input methods</string>
 
     <string name="fast_scroll_alphabet">\u0020ABCDEFGHIJKLMNOPQRSTUVWXYZ</string>
     <string name="fast_scroll_numeric_alphabet">\u00200123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ</string>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index cf9c00b..1183915 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1194,7 +1194,7 @@
     </style>
 
     <style name="TextAppearance.Holo.Widget.PopupMenu.Large">
-        <item name="android:textSize">22sp</item>
+        <item name="android:textSize">18sp</item>
     </style>
 
     <style name="TextAppearance.Holo.Widget.PopupMenu.Small">
@@ -1578,7 +1578,6 @@
     </style>
 
     <style name="Widget.Holo.Spinner.DropDown.ActionBar">
-        <item name="android:background">@android:drawable/spinner_cab_background_holo_dark</item>
     </style>
 
     <style name="Widget.Holo.CompoundButton.Star" parent="Widget.CompoundButton.Star">
@@ -1651,6 +1650,8 @@
     </style>
 
     <style name="Widget.Holo.ActionButton" parent="Widget.ActionButton">
+        <item name="android:minWidth">64dip</item>
+        <item name="android:gravity">center</item>
         <item name="android:paddingLeft">16dip</item>
         <item name="android:paddingRight">16dip</item>
         <item name="android:minHeight">56dip</item>
@@ -1677,9 +1678,6 @@
     </style>
 
     <style name="Widget.Holo.ActionBarView_TabBar" parent="Widget.ActionBarView_TabBar">
-        <item name="divider">?android:attr/dividerVertical</item>
-        <item name="showDividers">beginning|end</item>
-        <item name="dividerPadding">8dip</item>
     </style>
 
     <style name="Widget.Holo.ActionBarView_TabText" parent="Widget.ActionBarView_TabText">
@@ -1920,7 +1918,6 @@
     </style>
 
     <style name="Widget.Holo.Light.Spinner.DropDown.ActionBar">
-        <item name="android:background">@android:drawable/spinner_cab_background_holo_light</item>
     </style>
 
     <style name="Widget.Holo.Light.CompoundButton.Star" parent="Widget.CompoundButton.Star">
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index d070c30..971719e 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -624,10 +624,8 @@
 
     <!-- Default theme for input methods, which is used by the
          {@link android.inputmethodservice.InputMethodService} class.
-         this inherits from Theme.NoTitleBar, but makes the background
-         transparent, the window floating and translucent, and ensures that
-         it does not dim the UI behind it.  This also configures the window
-         with the standard IME animations and visuals. -->
+         this inherits from Theme.Panel, but sets up IME appropriate animations
+         and a few custom attributes. -->
     <style name="Theme.InputMethod" parent="Theme.Panel">
         <item name="android:windowAnimationStyle">@android:style/Animation.InputMethod</item>
         <item name="android:imeFullscreenBackground">@android:drawable/input_method_fullscreen_background</item>
@@ -635,6 +633,17 @@
         <item name="android:imeExtractExitAnimation">@android:anim/input_method_extract_exit</item>
     </style>
 
+    <!-- Default theme for modern holo style input methods, which is used by the
+         {@link android.inputmethodservice.InputMethodService} class.
+         this inherits from Theme.Panel, but sets up IME appropriate animations
+         and a few custom attributes. -->
+    <style name="Theme.Holo.InputMethod" parent="Theme.Holo.Panel">
+        <item name="android:windowAnimationStyle">@android:style/Animation.InputMethod</item>
+        <item name="android:imeFullscreenBackground">@android:drawable/input_method_fullscreen_background</item>
+        <item name="android:imeExtractEnterAnimation">@android:anim/input_method_extract_enter</item>
+        <item name="android:imeExtractExitAnimation">@android:anim/input_method_extract_exit</item>
+    </style>
+    
     <!-- Theme for the search input bar. -->
     <style name="Theme.SearchBar" parent="Theme.Holo.Light.Panel">
         <item name="windowContentOverlay">@null</item>        
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index 0e65df5..2126529 100755
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -48,6 +48,7 @@
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.Arrays;
 
 public class PackageManagerTests extends AndroidTestCase {
     private static final boolean localLOGV = true;
@@ -3105,6 +3106,164 @@
                 PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
     }
 
+    @LargeTest
+    public void testPackageObbPaths_Nonexistent() {
+        try {
+            final PackageManager pm = getPm();
+
+            // Invalid Java package name.
+            pm.getPackageObbPaths("=non-existent");
+
+            fail("Should not be able to get package OBB paths for non-existent package");
+        } catch (IllegalArgumentException e) {
+            // pass
+        }
+    }
+
+    @LargeTest
+    public void testPackageObbPaths_Initial() {
+        InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false);
+
+        try {
+            final PackageManager pm = getPm();
+
+            assertEquals("Initial obb paths should be null",
+                    null, pm.getPackageObbPaths(ip.pkg.packageName));
+        } finally {
+            cleanUpInstall(ip);
+        }
+    }
+
+    @LargeTest
+    public void testPackageObbPaths_Null() {
+        InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false);
+
+        try {
+            final PackageManager pm = getPm();
+
+            pm.setPackageObbPaths(ip.pkg.packageName, null);
+
+            assertEquals("Returned paths should be null",
+                    null, pm.getPackageObbPaths(ip.pkg.packageName));
+        } finally {
+            cleanUpInstall(ip);
+        }
+    }
+
+    @LargeTest
+    public void testPackageObbPaths_Empty() {
+        InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false);
+
+        try {
+            final PackageManager pm = getPm();
+
+            final String[] paths = new String[0];
+
+            pm.setPackageObbPaths(ip.pkg.packageName, paths);
+
+            assertEquals("Empty list should be interpreted as null",
+                    null, pm.getPackageObbPaths(ip.pkg.packageName));
+        } finally {
+            cleanUpInstall(ip);
+        }
+    }
+
+    @LargeTest
+    public void testPackageObbPaths_Single() {
+        InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false);
+
+        try {
+            final PackageManager pm = getPm();
+
+            final String[] paths = new String[] {
+                "/example/test",
+            };
+
+            pm.setPackageObbPaths(ip.pkg.packageName, paths.clone());
+
+            assertTrue("Previously set paths should be the same as the returned paths.",
+                    Arrays.equals(paths, pm.getPackageObbPaths(ip.pkg.packageName)));
+        } finally {
+            cleanUpInstall(ip);
+        }
+    }
+
+    @LargeTest
+    public void testPackageObbPaths_Multiple() {
+        InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false);
+
+        try {
+            final PackageManager pm = getPm();
+
+            final String[] paths = new String[] {
+                    "/example/test1",
+                    "/example/test2",
+            };
+
+            pm.setPackageObbPaths(ip.pkg.packageName, paths.clone());
+
+            assertTrue("Previously set paths should be the same as the returned paths.",
+                    Arrays.equals(paths, pm.getPackageObbPaths(ip.pkg.packageName)));
+        } finally {
+            cleanUpInstall(ip);
+        }
+    }
+
+    @LargeTest
+    public void testPackageObbPaths_Twice() {
+        InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false);
+
+        try {
+            final PackageManager pm = getPm();
+
+            final String[] paths = new String[] {
+                    "/example/test1",
+                    "/example/test2",
+            };
+
+            pm.setPackageObbPaths(ip.pkg.packageName, paths.clone());
+
+            assertTrue("Previously set paths should be the same as the returned paths.",
+                    Arrays.equals(paths, pm.getPackageObbPaths(ip.pkg.packageName)));
+
+            paths[0] = "/example/test3";
+            pm.setPackageObbPaths(ip.pkg.packageName, paths.clone());
+
+            assertTrue("Previously set paths should be the same as the returned paths.",
+                    Arrays.equals(paths, pm.getPackageObbPaths(ip.pkg.packageName)));
+        } finally {
+            cleanUpInstall(ip);
+        }
+    }
+
+    @LargeTest
+    public void testPackageObbPaths_ReplacePackage() {
+        InstallParams ip = sampleInstallFromRawResource(PackageManager.INSTALL_INTERNAL, false);
+
+        try {
+            final PackageManager pm = getPm();
+
+            final String[] paths = new String[] {
+                    "/example/test1",
+                    "/example/test2",
+            };
+
+            pm.setPackageObbPaths(ip.pkg.packageName, paths.clone());
+
+            Log.i(TAG, "Creating replaceReceiver");
+            final GenericReceiver receiver = new ReplaceReceiver(ip.pkg.packageName);
+
+            final int flags = PackageManager.INSTALL_REPLACE_EXISTING;
+            invokeInstallPackage(ip.packageURI, flags, receiver);
+            assertInstall(ip.pkg, flags, ip.pkg.installLocation);
+
+            assertTrue("Previously set paths should be the same as the returned paths.",
+                    Arrays.equals(paths, pm.getPackageObbPaths(ip.pkg.packageName)));
+        } finally {
+            cleanUpInstall(ip);
+        }
+    }
+
     /*---------- Recommended install location tests ----*/
     /*
      * TODO's
diff --git a/docs/html/guide/topics/advanced/aidl.jd b/docs/html/guide/topics/advanced/aidl.jd
new file mode 100644
index 0000000..fef46ec
--- /dev/null
+++ b/docs/html/guide/topics/advanced/aidl.jd
@@ -0,0 +1,387 @@
+page.title=Android Interface Definition Language (AIDL)
+@jd:body
+
+
+
+<p>AIDL (Android Interface Definition Language) is similar to other IDLs you might have
+worked with. It allows you to define the programming interface that both
+the client and service agree upon in order to communicate with each other and allows for
+interprocess communication (IPC). On Android, one process can not normally access the
+memory of another process. So to talk, they need to decompose their objects into primitives that the
+operating system can understand, and "marshall" the object across that boundary for you. The code to
+do that marshalling is tedious to write, so Android handles it for you with AIDL.</p>
+
+<p class="note"><strong>Note:</strong> Using AIDL is necessary only if you allow clients from
+different applications to access your service for IPC and want to handle multithreading in your
+service. If you do not need to perform IPC across
+different applications, you should create your interface <a href="Binder">implementing a
+Binder</a> or, if you want to perform IPC, but do not need to handle multithreading, then you
+should implement your interface <a href="#Messenger">using a Messenger</a>.</p>
+
+<p>Before you begin designing your AIDL interface, be aware that calls on to an AIDL interface are
+direct function calls.  You can not generally make assumptions about the thread in which the call
+will happen.  What happens is different depending on whether the call is from a thread in the
+local process, or coming from a remote process. Specifically:</p>
+
+<ul>
+<li>Calls from the local process are executed in the same thread that is making the call. If this is
+your main UI thread, that thread will continue executing into the aidl interface.  If it is another
+thread, that is one that will be executing your code.  Thus if only local threads are accessing the
+interface, you can completely control which threads are executing in it (but if that is the case,
+why are you defining an aidl interface at all?).</li>
+
+<li>Calls from a remote process are dispatched from a thread pool the platform maintains inside of
+your own process.  You must be prepared for incoming calls from unknown threads, with multiple calls
+happening at the same time.  In other words, an implementation of an aidl interface must be
+completely thread-safe.</li>
+
+<li>The "oneway" keyword modifies the behavior of remote calls.  When used, a remote call will not
+block until its call completes; it simply sends the transaction data and immediately returns.  The
+implementation of the interface will eventually receive this as a regular call from the {@link
+android.os.Binder} thread pool as a normal remote call. If "oneway" is used with a local call,
+there is no impact and the call is still synchronous.</li>
+</ul>
+
+
+<h2 id="Defining">Defining an AIDL Interface</h2>
+
+<p>You must define your AIDL interface in an {@code .aidl} file using the Java
+programming language syntax, then save it in the source code (in the {@code src/} directory) of both
+the application hosting the service and any other application that will bind to the service.</p>
+
+<p>When you build the projects containing the {@code .aidl} file, the Android SDK tools generate an
+{@link android.os.IBinder} class based on your AIDL interface (and saves the file in the {@code
+gen/} directory). This class defines the APIs you can call to perform RPC as an interface&mdash;you
+must implement the interface in your service.</p>
+
+<p>To create a bounded service using AIDL, follow these steps:</p>
+<ol>
+    <li><a href="#CreateAidl">Create the .aidl file</a>
+      <p>This file defines the programming interface with method signatures.</p>
+    </li>
+    <li><a href="#ImplementTheInterface">Implement the interface</a>
+      <p>The Android SDK tools generate an interface in the Java programming language, based on your
+{@code .aidl} file. This interface has an inner abstract class named {@code Stub} that extends
+{@link android.os.Binder} and implements methods from your AIDL interface. You must extend the
+{@code Stub} class and implement the methods.</p>
+    </li>
+    <li><a href="#ExposeTheInterface">Expose the interface to clients</a>
+      <p>Implement a {@link android.app.Service Service} and override {@link
+android.app.Service#onBind onBind()} to return your implementation of the {@code Stub}
+class.</p>
+    </li>
+</ol>
+
+<p class="caution"><strong>Caution:</strong> Any changes that you make to your AIDL interface after
+your first release must remain backward compatible in order to avoid breaking other applications
+that use your service. That is, because your {@code .aidl} file must be copied to other applications
+in order for them to access your service's interface, you must maintain support for the original
+interface.</p>
+
+
+<h3 id="CreateAidl">1. Create the .aidl file</h3>
+
+<p>AIDL uses a simple syntax that lets you declare an interface with one or more methods that can
+take parameters and return values. The parameters and return values can be of any type, even other
+AIDL-generated interfaces.</p>
+
+<p>The syntax for the {@code .aidl} file uses the Java programming language. The file defines a
+single interface and requires only the interface declaration and method signatures.</p>
+
+<p>By default, AIDL supports the following data types:</p>
+
+<ul>
+  <li>All primitive types in the Java programming language ({@code int}, {@code long}, {@code
+char}, {@code boolean}, etc.)</li>
+  <li>{@link java.lang.String}</li>
+  <li>{@link java.lang.CharSequence}</li>
+  <li>{@link java.util.List}
+    <p>All elements in the {@link java.util.List} must be one of the supported data types in this
+list or one of the other AIDL-generated interfaces or parcelables you've declared. A {@link
+java.util.List} may optionally be used as a "generic" class (e.g. <code>List&lt;String&gt;</code>).
+The actual concrete class that the other side will receive will always be an {@link
+java.util.ArrayList}, although the method will be generated to use the {@link
+java.util.List} interface.</p>
+  </li>
+  <li>{@link java.util.Map}
+    <p>All elements in the {@link java.util.Map} must be one of the supported data types in this
+list or one of the other AIDL-generated interfaces or parcelables you've declared.  Generic maps,
+(such as those of the form
+{@code Map&lt;String,Integer&gt;} are not supported. The actual concrete class that the other side
+will receive will always be a {@link java.util.HashMap}, although the method will be generated to
+use the {@link java.util.Map} interface.</p>
+  </li>
+</ul>
+
+<p>You must include an {@code import} statement for each additional type not listed above, even if
+they are defined in the same package as your interface.</p>
+
+<p>When defining methods for your service interface, be aware that:</p>
+<ul>
+  <li>Methods can take zero or more parameters, and return a value or void.</li>
+  <li>All non-primitive parameters require a directional tag indicating which way the data will go.
+Either <code>in</code>, <code>out</code>, or <code>inout</code> (see the example below).
+    <p>Primitives are <code>in</code> by default, and cannot be otherwise.</p>
+    <p class="caution"><strong>Caution:</strong> You should limit the direction to what is truly
+needed, because marshalling parameters is expensive.</p></li>
+  <li>All code comments included in the {@code .aidl} file are included in the generated {@link
+android.os.IBinder} interface (except for comments before the import and package
+statements).</li>
+</ul>
+
+<p>Here is an example {@code .aidl} file:</p>
+
+<pre>
+// IRemoteService.aidl
+package com.example.android;
+
+// Declare any non-default types here with import statements
+
+/** Example service interface */
+interface IRemoteService {
+    /** Request the process ID of this service, to do evil things with it. */
+    int getPid();
+
+    /** Demonstrates some basic types that you can use as parameters
+     * and return values in AIDL.
+     */
+    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
+            double aDouble, String aString);
+}
+</pre>
+
+<p>Simply save your {@code .aidl} file in your project's {@code src/} directory and when you
+build your application, the SDK tools will generate the binder class file in your project's
+{@code gen/} directory. The generated file name matches the {@code .aidl} file name, but with a
+{@code .java} extension (for example, {@code IRemoteService.aidl} results in {@code
+IRemoteService.java}).</p>
+
+<p>If you use Eclipse, the incremental build generates the binder class almost immediately. If you
+do not use Eclipse, then the Ant tool generates the binder class next time you build your
+application&mdash;you should build your project with <code>ant debug</code> (or <code>ant
+release</code>) as soon as you're finished writing the {@code .aidl} file, so that your code can
+link against the generated class.</p>
+
+
+<h3 id="ImplementTheInterface">2. Implement the interface</h3>
+
+<p>When you build your application, the Android SDK tools generate a {@code .java} interface file
+named after your {@code .aidl} file. The generated interface includes a subclass named {@code Stub}
+that is an abstract implementation of its parent interface (for example, {@code
+YourInterface.Stub}) and declares all the methods from the {@code .aidl} file.</p>
+
+<p class="note"><strong>Note:</strong> {@code Stub} also
+defines a few helper methods, most notably {@code asInterface()}, which takes an {@link
+android.os.IBinder} (usually the one passed to a client's {@link
+android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback method) and
+returns an instance of the stub interface. See the section <a href="#calling">Calling an IPC
+Method</a> for more details on how to make this cast.</p></p>
+
+<p>To implement the interface generated from the {@code .aidl}, extend the generated {@link
+android.os.Binder} interface (for example, {@code YourInterface.Stub}) and implement the methods
+inherited from the {@code .aidl} file.</p>
+
+<p>Here is an example implementation of an interface called {@code IRemoteService} (defined by the
+{@code IRemoteService.aidl} example, above) using an anonymous instance:</p>
+  
+<pre>
+private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
+    public int getPid(){
+        return Process.myPid();
+    }
+    public void basicTypes(int anInt, long aLong, boolean aBoolean,
+        float aFloat, double aDouble, String aString) {
+        // Does nothing
+    }
+};
+</pre>
+
+<p>Now the {@code mBinder} is an instance of the {@code Stub} class (a {@link android.os.Binder}),
+which defines the RPC interface for the service. In the next step, this instance is exposed to
+clients so they can interact with the service.</p>
+
+<p>There are a few rules you should be aware of when implementing your AIDL interface: </p>
+<ul>
+    <li>Incoming calls are not guaranteed to be executed on the main thread, so you need to think
+about multithreading from the start and properly build your service to be thread-safe.</li>
+    <li>By default, RPC calls are synchronous. If you know that the service takes more than a few
+milliseconds to complete a request, you should not call it from the activity's main thread, because
+it might hang the application (Android might display an &quot;Application is Not Responding&quot;
+dialog)&mdash;you should usually call them from a separate thread in the client. </li>
+    <li>No exceptions that you throw are sent back to the caller.</li>
+    <li>Only methods are supported; you cannot expose static fields in AIDL.</li>
+</ul>
+
+
+<h3 id="ExposeTheInterface">3. Expose the interface to clients</h3>
+
+<p>Once you've implemented the interface for your service, you need to expose it to
+clients so they can bind to it. To expose the interface
+for your service, extend {@link android.app.Service Service} and implement {@link
+android.app.Service#onBind onBind()} to return an instance of your class that implements
+the generated {@code Stub} (as discussed in the previous section). Here's an example
+service that exposes the {@code IRemoteService} example interface to clients. </p>
+
+<pre>
+public class RemoteService extends Service {
+    &#64;Override
+    public void onCreate() {
+        super.onCreate();
+    }
+
+    &#64;Override
+    public IBinder onBind(Intent intent) {
+        // Return the interface
+        return mBinder;
+    }
+
+    private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
+        public int getPid(){
+            return Process.myPid();
+        }
+        public void basicTypes(int anInt, long aLong, boolean aBoolean,
+            float aFloat, double aDouble, String aString) {
+            // Does nothing
+        }
+    };
+}
+</pre>
+
+<p>Now, when a client (such as an activity) calls {@link android.content.Context#bindService
+bindService()} to connect to this service, the client's {@link
+android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback receives the
+{@code mBinder} instance returned by the service's {@link android.app.Service#onBind onBind()}
+method.</p>
+
+<p>The client must also have access to the interface class, so if the client and service are in
+separate applications, then the client's application must have a copy of the {@code .aidl} file
+in its {@code src/} directory (which generates the {@code android.os.Binder}
+interface&mdash;providing the client access to the AIDL methods).</p>
+
+<p>When the client receives the {@link android.os.IBinder} in the {@link
+android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback, it must call
+<code><em>YourServiceInterface</em>.Stub.asInterface(service)</code> to cast the returned
+parameter to <code><em>YourServiceInterface</em></code> type. For example:</p>
+
+<pre>
+IRemoteService mIRemoteService;
+private ServiceConnection mConnection = new ServiceConnection() {
+    // Called when the connection with the service is established
+    public void onServiceConnected(ComponentName className, IBinder service) {
+        // Following the example above for an AIDL interface,
+        // this gets an instance of the IRemoteInterface, which we can use to call on the service
+        mIRemoteService = IRemoteService.Stub.asInterface(service);
+    }
+
+    // Called when the connection with the service disconnects unexpectedly
+    public void onServiceDisconnected(ComponentName className) {
+        Log.e(TAG, "onServiceDisconnected");
+    }
+};
+</pre>
+
+<p>For more sample code, see the <a
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">{@code
+RemoteService.java}</a> class in <a
+href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>.</p>
+
+
+
+
+
+
+  
+
+<h2 id="PassingObjects">Passing Objects over IPC</h2>
+
+<p>If you have a class that you would like to send from one process to another through
+an IPC interface, you can do that. However, you must ensure that the code for your class is
+available to the other side of the IPC and the class must support the {@link
+android.os.Parcelable} interface, in order for the objects to be decomposed into primitives and
+marshalled across processes by the Android system.</p>
+
+<p>There are five parts to making a class support the {@link android.os.Parcelable} protocol:</b>
+<ol>
+<li>Make your class implement the {@link android.os.Parcelable} interface.</li>
+<li>Implement {@link android.os.Parcelable#writeToParcel writeToParcel}, which takes the
+current state of the object and writes it to a {@link android.os.Parcel}.</li>
+<li>Add a static field called <code>CREATOR</code> to your class which is an object implementing
+the {@link android.os.Parcelable.Creator Parcelable.Creator} interface.</li>
+<li>Finally, create an {@code .aidl} file that declares your parcelable class (as shown for the
+{@code Rect.aidl} file, below).
+  <p>If you are using a custom build process, do <em>not</em> add the {@code .aidl} file to your
+build. Similar to a header file in the C language, this {@code .aidl} file isn't compiled.</p></li>
+</ol>
+
+<p>AIDL will use these methods and fields in the code it generates to marshall and unmarshall
+your objects.</p>
+
+<p>For example, here is a {@code Rect.aidl} file to create a {@code Rect} class that's
+parcelable:</p>
+
+<pre>
+package android.graphics;
+
+// Declare Rect so AIDL can find it and knows that it implements
+// the parcelable protocol.
+parcelable Rect;
+</pre>
+
+<p>And here is an example of how the {@link android.graphics.Rect} class implements the
+{@link android.os.Parcelable} protocol.</p>
+
+<pre>
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public final class Rect implements Parcelable {
+    public int left;
+    public int top;
+    public int right;
+    public int bottom;
+
+    public static final Parcelable.Creator&lt;Rect&gt; CREATOR = new
+Parcelable.Creator&lt;Rect&gt;() {
+        public Rect createFromParcel(Parcel in) {
+            return new Rect(in);
+        }
+
+        public Rect[] newArray(int size) {
+            return new Rect[size];
+        }
+    };
+
+    public Rect() {
+    }
+
+    private Rect(Parcel in) {
+        readFromParcel(in);
+    }
+
+    public void writeToParcel(Parcel out) {
+        out.writeInt(left);
+        out.writeInt(top);
+        out.writeInt(right);
+        out.writeInt(bottom);
+    }
+
+    public void readFromParcel(Parcel in) {
+        left = in.readInt();
+        top = in.readInt();
+        right = in.readInt();
+        bottom = in.readInt();
+    }
+}
+</pre>
+
+<p>The marshalling in the {@code Rect} class is pretty simple.  Take a look at the other
+methods on {@link android.os.Parcel} to see the other kinds of values you can write
+to a Parcel.</p>
+
+<p class="warning"><strong>Warning:</strong> Don't forget the security implications of receiving
+data from other processes.  In this case, the {@code Rect} will read four numbers from the {@link
+android.os.Parcel}, but it is up to you to ensure that these are within the acceptable range of
+values for whatever the caller is trying to do.  See <a
+href="{@docRoot}guide/topics/security/security.html">Security and Permissions</a> for more
+information about how to keep your application secure from malware.</p>
+
diff --git a/docs/html/guide/topics/fundamentals/bound-services.jd b/docs/html/guide/topics/fundamentals/bound-services.jd
new file mode 100644
index 0000000..e5d626c
--- /dev/null
+++ b/docs/html/guide/topics/fundamentals/bound-services.jd
@@ -0,0 +1,675 @@
+page.title=Bound Services
+parent.title=Services
+parent.link=services.html
+@jd:body
+
+
+<div id="qv-wrapper">
+<ol id="qv">
+<h2>Quickview</h2>
+<ul>
+  <li>A bound service allows other components to bind to it, in order to interact with it and
+perform interprocess communication</li>
+  <li>A bound service is destroyed once all clients unbind, unless the service was also started</li>
+</ul>
+<h2>In this document</h2>
+<ol>
+  <li><a href="#Basics">The Basics</a></li>
+  <li><a href="#Creating">Creating a Bound Service</a>
+    <ol>
+      <li><a href="#Binder">Extending the Binder class</a></li>
+      <li><a href="#Messenger">Using a Messenger</a></li>
+    </ol>
+  </li>
+  <li><a href="#Binding">Binding to a Service</a></li>
+  <li><a href="#Lifecycle">Managing the Lifecycle of a Bound Service</a></li>
+</ol>
+
+<h2>Key classes</h2>
+<ol>
+  <li>{@link android.app.Service}</li>
+  <li>{@link android.content.ServiceConnection}</li>
+  <li>{@link android.os.IBinder}</li>
+</ol>
+
+<h2>Samples</h2>
+<ol>
+  <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">{@code
+      RemoteService}</a></li>
+  <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code
+      LocalService}</a></li>
+</ol>
+
+<h2>See also</h2>
+<ol>
+  <li><a href="{@docRoot}guide/topics/fundamentals/services.html">Services</a></li>
+</ol>
+</div>
+
+
+<p>A bound service is the server in a client-server interface. A bound service allows components
+(such as activities) to bind to the service, send requests, receive responses, and even perform
+interprocess communication (IPC). A bound service typically lives only while it serves another
+application component and does not run in the background indefinitely.</p>
+
+<p>This document shows you how to create a bound service, including how to bind
+to the service from other application components. However, you should also refer to the <a
+href="{@docRoot}guide/topics/fundamentals/services.html">Services</a> document for additional
+information about services in general, such as how to deliver notifications from a service, set
+the service to run in the foreground, and more.</p>
+
+
+<h2 id="Basics">The Basics</h2>
+
+<p>A bound service is an implementation of the {@link android.app.Service} class that allows
+other applications to bind to it and interact with it. To provide binding for a
+service, you must implement the {@link android.app.Service#onBind onBind()} callback method. This
+method returns an {@link android.os.IBinder} object that defines the programming interface that
+clients can use to interact with the service.</p>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+  <h3>Binding to a Started Service</h3>
+
+<p>As discussed in the <a href="{@docRoot}guide/topics/fundamentals/services.html">Services</a>
+document, you can create a service that is both started and bound. That is, the service can be
+started by calling {@link android.content.Context#startService startService()}, which allows the
+service to run indefinitely, and also allow a client to bind to the service by calling {@link
+android.content.Context#bindService bindService()}.
+  <p>If you do allow your service to be started and bound, then when the service has been
+started, the system does <em>not</em> destroy the service when all clients unbind. Instead, you must
+explicitly stop the service, by calling {@link android.app.Service#stopSelf stopSelf()} or {@link
+android.content.Context#stopService stopService()}.</p>
+
+<p>Although you should usually implement either {@link android.app.Service#onBind onBind()}
+<em>or</em> {@link android.app.Service#onStartCommand onStartCommand()}, it's sometimes necessary to
+implement both. For example, a music player might find it useful to allow its service to run
+indefinitely and also provide binding. This way, an activity can start the service to play some
+music and the music continues to play even if the user leaves the application. Then, when the user
+returns to the application, the activity can bind to the service to regain control of playback.</p>
+
+<p>Be sure to read the section about <a href="#Lifecycle">Managing the Lifecycle of a Bound
+Service</a>, for more information about the service lifecycle when adding binding to a
+started service.</p>
+</div>
+</div>
+
+<p>A client can bind to the service by calling {@link android.content.Context#bindService
+bindService()}. When it does, it must provide an implementation of {@link
+android.content.ServiceConnection}, which monitors the connection with the service. The {@link
+android.content.Context#bindService bindService()} method returns immediately without a value, but
+when the Android system creates the connection between the
+client and service, it calls {@link
+android.content.ServiceConnection#onServiceConnected onServiceConnected()} on the {@link
+android.content.ServiceConnection}, to deliver the {@link android.os.IBinder} that
+the client can use to communicate with the service.</p>
+
+<p>Multiple clients can connect to the service at once. However, the system calls your service's
+{@link android.app.Service#onBind onBind()} method to retrieve the {@link android.os.IBinder} only
+when the first client binds. The system then delivers the same {@link android.os.IBinder} to any
+additional clients that bind, without calling {@link android.app.Service#onBind onBind()} again.</p>
+
+<p>When the last client unbinds from the service, the system destroys the service (unless the
+service was also started by {@link android.content.Context#startService startService()}).</p>
+
+<p>When you implement your bound service, the most important part is defining the interface
+that your {@link android.app.Service#onBind onBind()} callback method returns. There are a few
+different ways you can define your service's {@link android.os.IBinder} interface and the following
+section discusses each technique.</p>
+
+
+
+<h2 id="Creating">Creating a Bound Service</h2>
+
+<p>When creating a service that provides binding, you must provide an {@link android.os.IBinder}
+that provides the programming interface that clients can use to interact with the service. There
+are three ways you can define the interface:</p>
+
+<dl>
+  <dt><a href="#Binder">Extending the Binder class</a></dt>
+  <dd>If your service is private to your own application and runs in the same process as the client
+(which is common), you should create your interface by extending the {@link android.os.Binder} class
+and returning an instance of it from
+{@link android.app.Service#onBind onBind()}. The client receives the {@link android.os.Binder} and
+can use it to directly access public methods available in either the {@link android.os.Binder}
+implementation or even the {@link android.app.Service}.
+  <p>This is the preferred technique when your service is merely a background worker for your own
+application. The only reason you would not create your interface this way is because
+your service is used by other applications or across separate processes.</dd>
+
+  <dt><a href="#Messenger">Using a Messenger</a></dt>
+  <dd>If you need your interface to work across different processes, you can create
+an interface for the service with a {@link android.os.Messenger}. In this manner, the service
+defines a {@link android.os.Handler} that responds to different types of {@link
+android.os.Message} objects. This {@link android.os.Handler}
+is the basis for a {@link android.os.Messenger} that can then share an {@link android.os.IBinder}
+with the client, allowing the client to send commands to the service using {@link
+android.os.Message} objects. Additionally, the client can define a {@link android.os.Messenger} of
+its own so the service can send messages back.
+  <p>This is the simplest way to perform interprocess communication (IPC), because the {@link
+android.os.Messenger} queues all requests into a single thread so that you don't have to design
+your service to be thread-safe.</p>
+  </dd>
+
+  <dt>Using AIDL</dt>
+  <dd>AIDL (Android Interface Definition Language) performs all the work to decompose objects into
+primitives that the operating system can understand and marshall them across processes to perform
+IPC. The previous technique, using a {@link android.os.Messenger}, is actually based on AIDL as
+its underlying structure. As mentioned above, the {@link android.os.Messenger} creates a queue of
+all the client requests in a single thread, so the service receives requests one at a time. If,
+however, you want your service to handle multiple requests simultaneously, then you can use AIDL
+directly. In this case, your service must be capable of multi-threading and be built thread-safe.
+  <p>To use AIDL directly, you must
+create an {@code .aidl} file that defines the programming interface. The Android SDK tools use
+this file to generate an abstract class that implements the interface and handles IPC, which you
+can then extend within your service.</p>
+  </dd>
+</dl>
+
+  <p class="note"><strong>Note:</strong> Most applications <strong>should not</strong> use AIDL to
+create a bound service, because it may require multithreading capabilities and
+can result in a more complicated implementation. As such, AIDL is not suitable for most applications
+and this document does not discuss how to use it for your service. If you're certain that you need
+to use AIDL directly, see the <a href="{@docRoot}guide/topics/advanced/aidl.html">AIDL</a>
+document.</p>
+
+
+
+
+<h3 id="Binder">Extending the Binder class</h3>
+
+<p>If your service is used only by the local application and does not need to work across processes,
+then you can implement your own {@link android.os.Binder} class that provides your client direct
+access to public methods in the service.</p>
+
+<p class="note"><strong>Note:</strong> This works only if the client and service are in the same
+application and process, which is most common. For example, this would work well for a music
+application that needs to bind an activity to its own service that's playing music in the
+background.</p>
+
+<p>Here's how to set it up:</p>
+<ol>
+  <li>In your service, create an instance of {@link android.os.Binder} that either:
+    <ul>
+      <li>contains public methods that the client can call</li>
+      <li>returns the current {@link android.app.Service} instance, which has public methods the
+client can call</li>
+      <li>or, returns an instance of another class hosted by the service with public methods the
+client can call</li>
+    </ul>
+  <li>Return this instance of {@link android.os.Binder} from the {@link
+android.app.Service#onBind onBind()} callback method.</li>
+  <li>In the client, receive the {@link android.os.Binder} from the {@link
+android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback method and
+make calls to the bound service using the methods provided.</li>
+</ol>
+
+<p class="note"><strong>Note:</strong> The reason the service and client must be in the same
+application is so the client can cast the returned object and properly call its APIs. The service
+and client must also be in the same process, because this technique does not perform any
+marshalling across processes.</p>
+
+<p>For example, here's a service that provides clients access to methods in the service through
+a {@link android.os.Binder} implementation:</p>
+
+<pre>
+public class LocalService extends Service {
+    // Binder given to clients
+    private final IBinder mBinder = new LocalBinder();
+    // Random number generator
+    private final Random mGenerator = new Random();
+
+    /**
+     * Class used for the client Binder.  Because we know this service always
+     * runs in the same process as its clients, we don't need to deal with IPC.
+     */
+    public class LocalBinder extends Binder {
+        LocalService getService() {
+            // Return this instance of LocalService so clients can call public methods
+            return LocalService.this;
+        }
+    }
+
+    &#64;Override
+    public IBinder onBind(Intent intent) {
+        return mBinder;
+    }
+
+    /** method for clients */
+    public int getRandomNumber() {
+      return mGenerator.nextInt(100);
+    }
+}
+</pre>
+
+<p>The {@code LocalBinder} provides the {@code getService()} method for clients to retrieve the
+current instance of {@code LocalService}. This allows clients to call public methods in the
+service. For example, clients can call {@code getRandomNumber()} from the service.</p>
+
+<p>Here's an activity that binds to {@code LocalService} and calls {@code getRandomNumber()}
+when a button is clicked:</p>
+
+<pre>
+public class BindingActivity extends Activity {
+    LocalService mService;
+    boolean mBound = false;
+
+    &#64;Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+    }
+
+    &#64;Override
+    protected void onStart() {
+        super.onStart();
+        // Bind to LocalService
+        Intent intent = new Intent(this, LocalService.class);
+        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
+    }
+
+    &#64;Override
+    protected void onStop() {
+        super.onStop();
+        // Unbind from the service
+        if (mBound) {
+            unbindService(mConnection);
+            mBound = false;
+        }
+    }
+
+    /** Called when a button is clicked (the button in the layout file attaches to
+      * this method with the android:onClick attribute) */
+    public void onButtonClick(View v) {
+        if (mBound) {
+            // Call a method from the LocalService.
+            // However, if this call were something that might hang, then this request should
+            // occur in a separate thread to avoid slowing down the activity performance.
+            int num = mService.getRandomNumber();
+            Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
+        }
+    }
+
+    /** Defines callbacks for service binding, passed to bindService() */
+    private ServiceConnection mConnection = new ServiceConnection() {
+
+        &#64;Override
+        public void onServiceConnected(ComponentName className,
+                IBinder service) {
+            // We've bound to LocalService, cast the IBinder and get LocalService instance
+            LocalBinder binder = (LocalBinder) service;
+            mService = binder.getService();
+            mBound = true;
+        }
+
+        &#64;Override
+        public void onServiceDisconnected(ComponentName arg0) {
+            mBound = false;
+        }
+    };
+}
+</pre>
+
+<p>The above sample shows how the client binds to the service using an implementation of
+{@link android.content.ServiceConnection} and the {@link
+android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback. The next
+section provides more information about this process of binding to the service.</p>
+
+<p class="note"><strong>Note:</strong> The example above doesn't explicitly unbind from the service,
+but all clients should unbind at an appropriate time (such as when the activity pauses).</p>
+
+<p>For more sample code, see the <a
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code
+LocalService.java}</a> class and the <a
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceActivities.html">{@code
+LocalServiceActivities.java}</a> class in <a
+href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>.</p>
+
+
+
+
+
+<h3 id="Messenger">Using a Messenger</h3>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+  <h4>Compared to AIDL</h4>
+  <p>When you need to perform IPC, using a {@link android.os.Messenger} for your interface is
+simpler than implementing it with AIDL, because {@link android.os.Messenger} queues
+all calls to the service, whereas, a pure AIDL interface sends simultaneous requests to the
+service, which must then handle multi-threading.</p>
+  <p>For most applications, the service doesn't need to perform multi-threading, so using a {@link
+android.os.Messenger} allows the service to handle one call at a time. If it's important
+that your service be multi-threaded, then you should use <a
+href="{@docRoot}guide/topics/advanced/aidl.html">AIDL</a> to define your interface.</p>
+</div>
+</div>
+
+<p>If you need your service to communicate with remote processes, then you can use a
+{@link android.os.Messenger} to provide the interface for your service. This technique allows
+you to perform interprocess communication (IPC) without the need to use AIDL.</p>
+
+<p>Here's a summary of how to use a {@link android.os.Messenger}:</p>
+
+<ul>
+  <li>The service implements a {@link android.os.Handler} that receives a callback for each
+call from a client.</li>
+  <li>The {@link android.os.Handler} is used to create a {@link android.os.Messenger} object
+(which is a reference to the {@link android.os.Handler}).</li>
+  <li>The {@link android.os.Messenger} creates an {@link android.os.IBinder} that the service
+returns to clients from {@link android.app.Service#onBind onBind()}.</li>
+  <li>Clients use the {@link android.os.IBinder} to instantiate the {@link android.os.Messenger}
+(that references the service's {@link android.os.Handler}), which the client uses to send
+{@link android.os.Message} objects to the service.</li>
+  <li>The service receives each {@link android.os.Message} in its {@link
+android.os.Handler}&mdash;specifically, in the {@link android.os.Handler#handleMessage
+handleMessage()} method.</li>
+</ul>
+
+
+<p>In this way, there are no "methods" for the client to call on the service. Instead, the
+client delivers "messages" ({@link android.os.Message} objects) that the service receives in
+its {@link android.os.Handler}.</p>
+
+<p>Here's a simple example service that uses a {@link android.os.Messenger} interface:</p>
+
+<pre>
+public class MessengerService extends Service {
+    /** Command to the service to display a message */
+    static final int MSG_SAY_HELLO = 1;
+
+    /**
+     * Handler of incoming messages from clients.
+     */
+    class IncomingHandler extends Handler {
+        &#64;Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_SAY_HELLO:
+                    Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show();
+                    break;
+                default:
+                    super.handleMessage(msg);
+            }
+        }
+    }
+
+    /**
+     * Target we publish for clients to send messages to IncomingHandler.
+     */
+    final Messenger mMessenger = new Messenger(new IncomingHandler());
+
+    /**
+     * When binding to the service, we return an interface to our messenger
+     * for sending messages to the service.
+     */
+    &#64;Override
+    public IBinder onBind(Intent intent) {
+        Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show();
+        return mMessenger.getBinder();
+    }
+}
+</pre>
+
+<p>Notice that the {@link android.os.Handler#handleMessage handleMessage()} method in the
+{@link android.os.Handler} is where the service receives the incoming {@link android.os.Message}
+and decides what to do, based on the {@link android.os.Message#what} member.</p>
+
+<p>All that a client needs to do is create a {@link android.os.Messenger} based on the {@link
+android.os.IBinder} returned by the service and send a message using {@link
+android.os.Messenger#send send()}. For example, here's a simple activity that binds to the
+service and delivers the {@code MSG_SAY_HELLO} message to the service:</p>
+
+<pre>
+public class ActivityMessenger extends Activity {
+    /** Messenger for communicating with the service. */
+    Messenger mService = null;
+
+    /** Flag indicating whether we have called bind on the service. */
+    boolean mBound;
+
+    /**
+     * Class for interacting with the main interface of the service.
+     */
+    private ServiceConnection mConnection = new ServiceConnection() {
+        public void onServiceConnected(ComponentName className, IBinder service) {
+            // This is called when the connection with the service has been
+            // established, giving us the object we can use to
+            // interact with the service.  We are communicating with the
+            // service using a Messenger, so here we get a client-side
+            // representation of that from the raw IBinder object.
+            mService = new Messenger(service);
+            mBound = true;
+        }
+
+        public void onServiceDisconnected(ComponentName className) {
+            // This is called when the connection with the service has been
+            // unexpectedly disconnected -- that is, its process crashed.
+            mService = null;
+            mBound = false;
+        }
+    };
+
+    public void sayHello(View v) {
+        if (!mBound) return;
+        // Create and send a message to the service, using a supported 'what' value
+        Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0);
+        try {
+            mService.send(msg);
+        } catch (RemoteException e) {
+            e.printStackTrace();
+        }
+    }
+
+    &#64;Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+    }
+
+    &#64;Override
+    protected void onStart() {
+        super.onStart();
+        // Bind to the service
+        bindService(new Intent(this, MessengerService.class), mConnection,
+            Context.BIND_AUTO_CREATE);
+    }
+
+    &#64;Override
+    protected void onStop() {
+        super.onStop();
+        // Unbind from the service
+        if (mBound) {
+            unbindService(mConnection);
+            mBound = false;
+        }
+    }
+}
+</pre>
+
+<p>Notice that this example does not show how the service can respond to the client. If you want the
+service to respond, then you need to also create a {@link android.os.Messenger} in the client. Then
+when the client receives the {@link android.content.ServiceConnection#onServiceConnected
+onServiceConnected()} callback, it sends a {@link android.os.Message} to the service that includes
+the client's {@link android.os.Messenger} in the {@link android.os.Message#replyTo} parameter
+of the {@link android.os.Messenger#send send()} method.</p>
+
+<p>You can see an example of how to provide two-way messaging in the <a
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerService.html">{@code
+MessengerService.java}</a> (service) and <a
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerServiceActivities.html">{@code
+MessengerServiceActivities.java}</a> (client) samples.</p>
+
+
+
+
+
+<h2 id="Binding">Binding to a Service</h2>
+
+<p>Application components (clients) can bind to a service by calling
+{@link android.content.Context#bindService bindService()}. The Android
+system then calls the service's {@link android.app.Service#onBind
+onBind()} method, which returns an {@link android.os.IBinder} for interacting with the service.</p>
+
+<p>The binding is asynchronous. {@link android.content.Context#bindService
+bindService()} returns immediately and does <em>not</em> return the {@link android.os.IBinder} to
+the client. To receive the {@link android.os.IBinder}, the client must create an instance of {@link
+android.content.ServiceConnection} and pass it to {@link android.content.Context#bindService
+bindService()}. The {@link android.content.ServiceConnection} includes a callback method that the
+system calls to deliver the {@link android.os.IBinder}.</p>
+
+<p class="note"><strong>Note:</strong> Only activities, services, and content providers can bind
+to a service&mdash;you <strong>cannot</strong> bind to a service from a broadcast receiver.</p>
+
+<p>So, to bind to a service from your client, you must: </p>
+<ol>
+  <li>Implement {@link android.content.ServiceConnection}.
+    <p>Your implementation must override two callback methods:</p>
+    <dl>
+      <dt>{@link android.content.ServiceConnection#onServiceConnected onServiceConnected()}</dt>
+        <dd>The system calls this to deliver the {@link android.os.IBinder} returned by
+the service's {@link android.app.Service#onBind onBind()} method.</dd>
+      <dt>{@link android.content.ServiceConnection#onServiceDisconnected
+onServiceDisconnected()}</dt>
+        <dd>The Android system calls this when the connection to the service is unexpectedly
+lost, such as when the service has crashed or has been killed. This is <em>not</em> called when the
+client unbinds.</dd>
+    </dl>
+  </li>
+  <li>Call {@link
+android.content.Context#bindService bindService()}, passing the {@link
+android.content.ServiceConnection} implementation. </li>
+  <li>When the system calls your {@link android.content.ServiceConnection#onServiceConnected
+onServiceConnected()} callback method, you can begin making calls to the service, using
+the methods defined by the interface.</li>
+  <li>To disconnect from the service, call {@link
+android.content.Context#unbindService unbindService()}.
+    <p>When your client is destroyed, it will unbind from the service, but you should always unbind
+when you're done interacting with the service or when your activity pauses so that the service can
+shutdown while its not being used. (Appropriate times to bind and unbind is discussed
+more below.)</p>
+  </li>
+</ol>
+
+<p>For example, the following snippet connects the client to the service created above by
+<a href="#Binder">extending the Binder class</a>, so all it must do is cast the returned
+{@link android.os.IBinder} to the {@code LocalService} class and request the {@code
+LocalService} instance:</p>
+
+<pre>
+LocalService mService;
+private ServiceConnection mConnection = new ServiceConnection() {
+    // Called when the connection with the service is established
+    public void onServiceConnected(ComponentName className, IBinder service) {
+        // Because we have bound to an explicit
+        // service that is running in our own process, we can
+        // cast its IBinder to a concrete class and directly access it.
+        LocalBinder binder = (LocalBinder) service;
+        mService = binder.getService();
+        mBound = true;
+    }
+
+    // Called when the connection with the service disconnects unexpectedly
+    public void onServiceDisconnected(ComponentName className) {
+        Log.e(TAG, "onServiceDisconnected");
+        mBound = false;
+    }
+};
+</pre>
+
+<p>With this {@link android.content.ServiceConnection}, the client can bind to a service by passing
+this it to {@link android.content.Context#bindService bindService()}. For example:</p>
+
+<pre>
+Intent intent = new Intent(this, LocalService.class);
+bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
+</pre>
+
+<ul>
+  <li>The first parameter of {@link android.content.Context#bindService bindService()} is an
+{@link android.content.Intent} that explicitly names the service to bind (thought the intent
+could be implicit).</li>
+<li>The second parameter is the {@link android.content.ServiceConnection} object.</li>
+<li>The third parameter is a flag indicating options for the binding. It should usually be {@link
+android.content.Context#BIND_AUTO_CREATE} in order to create the service if its not already alive.
+Other possible values are {@link android.content.Context#BIND_DEBUG_UNBIND}
+and {@link android.content.Context#BIND_NOT_FOREGROUND}, or {@code 0} for none.</li>
+</ul>
+
+
+<h3>Additional notes</h3>
+
+<p>Here are some important notes about binding to a service:</p>
+<ul>
+  <li>You should always trap {@link android.os.DeadObjectException} exceptions, which are thrown
+when the connection has broken. This is the only exception thrown by remote methods.</li>
+  <li>Objects are reference counted across processes. </li>
+  <li>You should usually pair the binding and unbinding during
+matching bring-up and tear-down moments of the client's lifecycle. For example:
+    <ul>
+      <li>If you only need to interact with the service while your activity is visible, you
+should bind during {@link android.app.Activity#onStart onStart()} and unbind during {@link
+android.app.Activity#onStop onStop()}.</li>
+      <li>If you want your activity to receive responses even while it is stopped in the
+background, then you can bind during {@link android.app.Activity#onCreate onCreate()} and unbind
+during {@link android.app.Activity#onDestroy onDestroy()}. Beware that this implies that your
+activity needs to use the service the entire time it's running (even in the background), so if
+the service is in another process, then you increase the weight of the process and it becomes
+more likely that the system will kill it.</li>
+    </ul>
+    <p class="note"><strong>Note:</strong> You should usually <strong>not</strong> bind and unbind
+during your activity's {@link android.app.Activity#onResume onResume()} and {@link
+android.app.Activity#onPause onPause()}, because these callbacks occur at every lifecycle transition
+and you should keep the processing that occurs at these transitions to a minimum. Also, if
+multiple activities in your application bind to the same service and there is a transition between
+two of those activities, the service may be destroyed and recreated as the current activity unbinds
+(during pause) before the next one binds (during resume). (This activity transition for how
+activities coordinate their lifecycles is described in the <a
+href="{@docRoot}guide/topics/fundamentals/activities.html#CoordinatingActivities">Activities</a>
+document.)</p>
+</ul>
+
+<p>For more sample code, showing how to bind to a service, see the <a
+href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">{@code
+RemoteService.java}</a> class in <a
+href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>.</p>
+
+
+
+
+
+<h2 id="Lifecycle">Managing the Lifecycle of a Bound Service</h2>
+
+<div class="figure" style="width:588px">
+<img src="{@docRoot}images/fundamentals/service_binding_tree_lifecycle.png" alt="" />
+<p class="img-caption"><strong>Figure 1.</strong> The lifecycle for a service that is started
+and also allows binding.</p>
+</div>
+
+<p>When a service is unbound from all clients, the Android system destroys it (unless it was also
+started with {@link android.app.Service#onStartCommand onStartCommand()}). As such, you don't have
+to manage the lifecycle of your service if it's purely a bound
+service&mdash;the Android system manages it for you based on whether it is bound to any clients.</p>
+
+<p>However, if you choose to implement the {@link android.app.Service#onStartCommand
+onStartCommand()} callback method, then you must explicitly stop the service, because the
+service is now considered to be <em>started</em>. In this case, the service runs until the service
+stops itself with {@link android.app.Service#stopSelf()} or another component calls {@link
+android.content.Context#stopService stopService()}, regardless of whether it is bound to any
+clients.</p>
+
+<p>Additionally, if your service is started and accepts binding, then when the system calls
+your {@link android.app.Service#onUnbind onUnbind()} method, you can optionally return
+{@code true} if you would like to receive a call to {@link android.app.Service#onRebind
+onRebind()} the next time a client binds to the service (instead of receiving a call to {@link
+android.app.Service#onBind onBind()}). {@link android.app.Service#onRebind
+onRebind()} returns void, but the client still receives the {@link android.os.IBinder} in its
+{@link android.content.ServiceConnection#onServiceConnected onServiceConnected()} callback.
+Below, figure 1 illustrates the logic for this kind of lifecycle.</p>
+
+<p>For more information about the lifecycle of an started service, see the <a
+href="{@docRoot}guide/topics/fundamentals/services.html#Lifecycle">Services</a> document.</p>
+
+
+
+
diff --git a/docs/html/guide/topics/fundamentals/services.jd b/docs/html/guide/topics/fundamentals/services.jd
new file mode 100644
index 0000000..df1eace
--- /dev/null
+++ b/docs/html/guide/topics/fundamentals/services.jd
@@ -0,0 +1,860 @@
+page.title=Services
+parent.title=Application Fundamentals
+parent.link=index.html
+@jd:body
+
+<div id="qv-wrapper">
+<ol id="qv">
+<h2>Quickview</h2>
+<ul>
+  <li>A service can run in the background to perform work even while the user is in a different
+application</li>
+  <li>A service can allow other components to bind to it, in order to interact with it and
+perform interprocess communication</li>
+  <li>A service runs in the main thread of the application that hosts it, by default</li>
+</ul>
+<h2>In this document</h2>
+<ol>
+<li><a href="#Basics">The Basics</a></li>
+<ol>
+  <li><a href="#Declaring">Declaring a service in the manifest</a></li>
+</ol>
+<li><a href="#CreatingAService">Creating a Started Service</a>
+  <ol>
+    <li><a href="#ExtendingIntentService">Extending the IntentService class</a></li>
+    <li><a href="#ExtendingService">Extending the Service class</a></li>
+    <li><a href="#StartingAService">Starting a service</a></li>
+    <li><a href="#Stopping">Stopping a service</a></li>
+  </ol>
+</li>
+<li><a href="#CreatingBoundService">Creating a Bound Service</a></li>
+<li><a href="#Notifications">Sending Notifications to the User</a></li>
+<li><a href="#Foreground">Running a Service in the Foreground</a></li>
+<li><a href="#Lifecycle">Managing the Lifecycle of a Service</a>
+<ol>
+  <li><a href="#LifecycleCallbacks">Implementing the lifecycle callbacks</a></li>
+</ol>
+</li>
+</ol>
+
+<h2>Key classes</h2>
+<ol>
+  <li>{@link android.app.Service}</li>
+  <li>{@link android.app.IntentService}</li>
+</ol>
+
+<h2>Samples</h2>
+<ol>
+  <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/ServiceStartArguments.html">{@code
+      ServiceStartArguments}</a></li>
+  <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code
+      LocalService}</a></li>
+</ol>
+
+<h2>See also</h2>
+<ol>
+<li><a href="{@docRoot}guide/topics/fundamentals/bound-services.html">Bound Services</a></li>
+</ol>
+
+</div>
+
+
+<p>A {@link android.app.Service} is an application component that can perform
+long-running operations in the background and does not provide a user interface. Another
+application component can start a service and it will continue to run in the background even if the
+user switches to another application. Additionally, a component can bind to a service to
+interact with it and even perform interprocess communication (IPC). For example, a service might
+handle network transactions, play music, perform file I/O, or interact with a content provider, all
+from the background.</p>
+
+<p>A service can essentially take two forms:</p>
+
+<dl>
+  <dt>Started</dt>
+  <dd>A service is "started" when an application component (such as an activity) starts it by
+calling {@link android.content.Context#startService startService()}. Once started, a service
+can run in the background indefinitely, even if the component that started it is destroyed. Usually,
+a started service performs a single operation and does not return a result to the caller.
+For example, it might download or upload a file over the network. When the operation is done, the
+service should stop itself.</dd>
+  <dt>Bound</dt>
+  <dd>A service is "bound" when an application component binds to it by calling {@link
+android.content.Context#bindService bindService()}. A bound service offers a client-server
+interface that allows components to interact with the service, send requests, get results, and even
+do so across processes with interprocess communication (IPC). A bound service runs only as long as
+another application component is bound to it. Multiple components can bind to the service at once,
+but when all of them unbind, the service is destroyed.</dd>
+</dl>
+
+<p>Although this documentation generally discusses these two types of services separately, your
+service can work both ways&mdash;it can be started (to run indefinitely) and also allow binding.
+It's simply a matter of whether you implement a couple callback methods: {@link
+android.app.Service#onStartCommand onStartCommand()} to allow components to start it and {@link
+android.app.Service#onBind onBind()} to allow binding.</p>
+
+<p>Regardless of whether your application is started, bound, or both, any application component
+can use the service (even from a separate application), in the same way that any component can use
+an activity&mdash;by starting it with an {@link android.content.Intent}. However, you can declare
+the service as private, in the manifest file, and block access from other applications. This is
+discussed more in the section about <a href="#Declaring">Declaring the service in the
+manifest</a>.</p>
+
+<p class="caution"><strong>Caution:</strong> A service runs in the
+main thread of its hosting process&mdash;the service does <strong>not</strong> create its own thread
+and does <strong>not</strong> run in a separate process (unless you specify otherwise). This means
+that, if your service is going to do any CPU intensive work or blocking operations (such as MP3
+playback or networking), you should create a new thread within the service to do that work. By using
+a separate thread, you will reduce the risk of Application Not Responding (ANR) errors and the
+application's main thread can remain dedicated to user interaction with your activities.</p>
+
+
+<h2 id="Basics">The Basics</h2>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+  <h3>Should you use a service or a thread?</h3>
+  <p>A service is simply a component that can run in the background even when the user is not
+interacting with your application. Thus, you should create a service only if that is what you
+need.</p>
+  <p>If you need to perform work outside your main thread, but only while the user is interacting
+with your application, then you should probably instead create a new thread and not a service. For
+example, if you want to play some music, but only while your activity is running, you might create
+a thread in {@link android.app.Activity#onCreate onCreate()}, start running it in {@link
+android.app.Activity#onStart onStart()}, then stop it in {@link android.app.Activity#onStop
+onStop()}. Also consider using {@link android.os.AsyncTask} or {@link android.os.HandlerThread},
+instead of the traditional {@link java.lang.Thread} class. See the <a
+href="{@docRoot}guide/topics/fundamentals/processes-and-threading.html#Threads">Processes and
+Threading</a> document for more information about threads.</p>
+  <p>Remember that if you do use a service, it still runs in your application's main thread by
+default, so you should still create a new thread within the service if it performs intensive or
+blocking operations.</p>
+</div>
+</div>
+
+<p>To create a service, you must create a subclass of {@link android.app.Service} (or one
+of its existing subclasses). In your implementation, you need to override some callback methods that
+handle key aspects of the service lifecycle and provide a mechanism for components to bind to
+the service, if appropriate. The most important callback methods you should override are:</p>
+
+<dl>
+  <dt>{@link android.app.Service#onStartCommand onStartCommand()}</dt>
+    <dd>The system calls this method when another component, such as an activity,
+requests that the service be started, by calling {@link android.content.Context#startService
+startService()}. Once this method executes, the service is started and can run in the
+background indefinitely. If you implement this, it is your responsibility to stop the service when
+its work is done, by calling {@link android.app.Service#stopSelf stopSelf()} or {@link
+android.content.Context#stopService stopService()}. (If you only want to provide binding, you don't
+need to implement this method.)</dd>
+  <dt>{@link android.app.Service#onBind onBind()}</dt>
+    <dd>The system calls this method when another component wants to bind with the
+service (such as to perform RPC), by calling {@link android.content.Context#bindService
+bindService()}. In your implementation of this method, you must provide an interface that clients
+use to communicate with the service, by returning an {@link android.os.IBinder}. You must always
+implement this method, but if you don't want to allow binding, then you should return null.</dd>
+  <dt>{@link android.app.Service#onCreate()}</dt>
+    <dd>The system calls this method when the service is first created, to perform one-time setup
+procedures (before it calls either {@link android.app.Service#onStartCommand onStartCommand()} or
+{@link android.app.Service#onBind onBind()}). If the service is already running, this method is not
+called.</dd>
+  <dt>{@link android.app.Service#onDestroy()}</dt>
+    <dd>The system calls this method when the service is no longer used and is being destroyed.
+Your service should implement this to clean up any resources such as threads, registered
+listeners, receivers, etc. This is the last call the service receives.</dd>
+</dl>
+
+<p>If a component starts the service by calling {@link
+android.content.Context#startService startService()} (which results in a call to {@link
+android.app.Service#onStartCommand onStartCommand()}), then the service
+remains running until it stops itself with {@link android.app.Service#stopSelf()} or another
+component stops it by calling {@link android.content.Context#stopService stopService()}.</p>
+
+<p>If a component calls
+{@link android.content.Context#bindService bindService()} to create the service (and {@link
+android.app.Service#onStartCommand onStartCommand()} is <em>not</em> called), then the service runs
+only as long as the component is bound to it. Once the service is unbound from all clients, the
+system destroys it.</p>
+
+<p>The Android system will force-stop a service only when memory is low and it must recover system
+resources for the activity that has user focus. If the service is bound to an activity that has user
+focus, then it's less likely to be killed, and if the service is declared to <a
+href="#Foreground">run in the foreground</a> (discussed later), then it will almost never be killed.
+Otherwise, if the service was started and is long-running, then the system will lower its position
+in the list of background tasks over time and the service will become highly susceptible to
+killing&mdash;if your service is started, then you must design it to gracefully handle restarts
+by the system. If the system kills your service, it restarts it as soon as resources become
+available again (though this also depends on the value you return from {@link
+android.app.Service#onStartCommand onStartCommand()}, as discussed later). For more information
+about when the system might destroy a service, see the <a
+href="{@docRoot}guide/topics/fundamentals/processes-and-threading.html">Processes and Threading</a>
+document.</p>
+
+<p>In the following sections, you'll see how you can create each type of service and how to use
+it from other application components.</p>
+
+
+
+<h3 id="Declaring">Declaring a service in the manifest</h3>
+
+<p>Like activities (and other components), you must declare all services in your application's
+manifest file.</p>
+
+<p>To decalare your service, add a <a
+href="{@docRoot}guide/topics/manifest/service-element.html">{@code &lt;service&gt;}</a> element
+as a child of the <a
+href="{@docRoot}guide/topics/manifest/application-element.html">{@code &lt;application&gt;}</a>
+element. For example:</p>
+
+<pre>
+&lt;manifest ... &gt;
+  ...
+  &lt;application ... &gt;
+      &lt;service android:name=".ExampleService" /&gt;
+      ...
+  &lt;/application&gt;
+&lt;/manifest&gt;
+</pre>
+
+<p>There are other attributes you can include in the <a
+href="{@docRoot}guide/topics/manifest/service-element.html">{@code &lt;service&gt;}</a> element to
+define properties such as permissions required to start the service and the process in
+which the service should run. See the <a
+href="{@docRoot}guide/topics/manifest/service-element.html">{@code &lt;service&gt;}</a> element
+reference for more information.</p>
+
+<p>Just like an activity, a service can define intent filters that allow other components to
+invoke the service using implicit intents. By declaring intent filters, components
+from any application installed on the user's device can potentially start your service if your
+service declares an intent filter that matches the intent another application passes to {@link
+android.content.Context#startService startService()}.</p>
+
+<p>If you plan on using your service only locally (other applications do not use it), then you
+don't need to (and should not) supply any intent filters. Without any intent filters, you must
+start the service using an intent that explicitly names the service class. More information
+about <a href="#StartingAService">starting a service</a> is discussed below.</p>
+
+<p>Additionally, you can ensure that your service is private to your application only if
+you include the <a
+href="{@docRoot}guide/topics/manifest/service-element.html#exported">{@code android:exported}</a>
+attribute and set it to {@code "false"}. This is effective even if your service supplies intent
+filters.</p>
+
+<p>For more information about creating intent filters for your service, see the <a
+href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and Intent Filters</a>
+document.</p>
+
+
+
+<h2 id="CreatingStartedService">Creating a Started Service</h2>
+
+<div class="sidebox-wrapper">
+<div class="sidebox">
+  <h2>Targeting Android 1.6 or lower</h2>
+  <p>If you're building an application for Android 1.6 or lower, you need
+to implement {@link android.app.Service#onStart onStart()}, instead of {@link
+android.app.Service#onStartCommand onStartCommand()} (in Android 2.0,
+{@link android.app.Service#onStart onStart()} was deprecated in favor of {@link
+android.app.Service#onStartCommand onStartCommand()}).</p>
+  <p>For more information about providing compatibility with versions of Android older than 2.0, see
+the {@link android.app.Service#onStartCommand onStartCommand()} documentation.</p>
+</div>
+</div>
+
+<p>A started service is one that another component starts by calling {@link
+android.content.Context#startService startService()}, resulting in a call to the service's
+{@link android.app.Service#onStartCommand onStartCommand()} method.</p>
+
+<p>When a service is started, it has a lifecycle that's independent of the
+component that started it and the service can run in the background indefinitely, even if
+the component that started it is destroyed. As such, the service should stop itself when its job
+is done by calling {@link android.app.Service#stopSelf stopSelf()}, or another component can stop it
+by calling {@link android.content.Context#stopService stopService()}.</p>
+
+<p>An application component such as an activity can start the service by calling {@link
+android.content.Context#startService startService()} and passing an {@link android.content.Intent}
+that specifies the service and includes any data for the service to use. The service receives
+this {@link android.content.Intent} in the {@link android.app.Service#onStartCommand
+onStartCommand()} method.</p>
+
+<p>For instance, suppose an activity needs to save some data to an online database. The activity can
+start a companion service and deliver it the data to save by passing an intent to {@link
+android.content.Context#startService startService()}. The service receives the intent in {@link
+android.app.Service#onStartCommand onStartCommand()}, connects to the Internet and performs the
+database transaction. When the transaction is done, the service stops itself and it is
+destroyed.</p>
+
+<p class="caution"><strong>Caution:</strong> A services runs in the same process as the application
+in which it is declared and in the main thread of that application, by default. So, if your service
+performs intensive or blocking operations while the user interacts with an activity from the same
+application, the service will slow down activity performance. To avoid impacting application
+performance, you should start a new thread inside the service.</p>
+
+<p>Traditionally, there are two classes you can extend to create a started service:</p>
+<dl>
+  <dt>{@link android.app.Service}</dt>
+  <dd>This is the base class for all services. When you extend this class, it's important that
+you create a new thread in which to do all the service's work, because the service uses your
+application's main thread, by default, which could slow the performance of any activity your
+application is running.</dd>
+  <dt>{@link android.app.IntentService}</dt>
+  <dd>This is a subclass of {@link android.app.Service} that uses a worker thread to handle all
+start requests, one at a time. This is the best option if you don't require that your service
+handle multiple requests simultaneously. All you need to do is implement {@link
+android.app.IntentService#onHandleIntent onHandleIntent()}, which receives the intent for each
+start request so you can do the background work.</dd>
+</dl>
+
+<p>The following sections describe how you can implement your service using either one for these
+classes.</p>
+
+
+<h3 id="ExtendingIntentService">Extending the IntentService class</h3>
+
+<p>Because most started services don't need to handle multiple requests simultaneously
+(which can actually be a dangerous multi-threading scenario), it's probably best if you
+implement your service using the {@link android.app.IntentService} class.</p>
+
+<p>The {@link android.app.IntentService} does the following:</p>
+
+<ul>
+  <li>Creates a default worker thread that executes all intents delivered to {@link
+android.app.Service#onStartCommand onStartCommand()} separate from your application's main
+thread.</li>
+  <li>Creates a work queue that passes one intent at a time to your {@link
+android.app.IntentService#onHandleIntent onHandleIntent()} implementation, so you never have to
+worry about multi-threading.</li>
+  <li>Stops the service after all start requests have been handled, so you never have to call
+{@link android.app.Service#stopSelf}.</li>
+  <li>Provides default implementation of {@link android.app.IntentService#onBind onBind()} that
+returns null.</li>
+  <li>Provides a default implementation of {@link android.app.IntentService#onStartCommand
+onStartCommand()} that sends the intent to the work queue and then to your {@link
+android.app.IntentService#onHandleIntent onHandleIntent()} implementation.</li>
+</ul>
+
+<p>All this adds up to the fact that all you need to do is implement {@link
+android.app.IntentService#onHandleIntent onHandleIntent()} to do the work provided by the
+client. (Though, you also need to provide a small constructor for the service.)</p>
+
+<p>Here's an example implementation of {@link android.app.IntentService}:</p>
+
+<pre>
+public class HelloIntentService extends IntentService {
+
+  /** 
+   * A constructor is required, and must call the super {@link android.app.IntentService#IntentService}
+   * constructor with a name for the worker thread.
+   */
+  public HelloIntentService() {
+      super("HelloIntentService");
+  }
+
+  /**
+   * The IntentService calls this method from the default worker thread with
+   * the intent that started the service. When this method returns, IntentService
+   * stops the service, as appropriate.
+   */
+  &#64;Override
+  protected void onHandleIntent(Intent intent) {
+      // Normally we would do some work here, like download a file.
+      // For our sample, we just sleep for 5 seconds.
+      long endTime = System.currentTimeMillis() + 5*1000;
+      while (System.currentTimeMillis() &lt; endTime) {
+          synchronized (this) {
+              try {
+                  wait(endTime - System.currentTimeMillis());
+              } catch (Exception e) {
+              }
+          }
+      }
+  }
+}
+</pre>
+
+<p>That's all you need: a constructor and an implementation of {@link
+android.app.IntentService#onHandleIntent onHandleIntent()}.</p>
+
+<p>If you decide to also override other callback methods, such as {@link
+android.app.IntentService#onCreate onCreate()}, {@link
+android.app.IntentService#onStartCommand onStartCommand()}, or {@link
+android.app.IntentService#onDestroy onDestroy()}, be sure to call the super implementation, so
+that the {@link android.app.IntentService} can properly handle the life of the worker thread.</p>
+
+<p>For example, {@link android.app.IntentService#onStartCommand onStartCommand()} must return
+the default implementation (which is how the intent gets delivered to {@link
+android.app.IntentService#onHandleIntent onHandleIntent()}):</p>
+
+<pre>
+&#64;Override
+public int onStartCommand(Intent intent, int flags, int startId) {
+    Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
+    return super.onStartCommand(intent,flags,startId);
+}
+</pre>
+
+<p>Besides {@link android.app.IntentService#onHandleIntent onHandleIntent()}, the only method
+from which you don't need to call the super class is {@link android.app.IntentService#onBind
+onBind()} (but you only need to implement that if your service allows binding).</p>
+
+<p>In the next section, you'll see how the same kind of service is implemented when extending
+the base {@link android.app.Service} class, which is a lot more code, but which might be
+appropriate if you need to handle simultaneous start requests.</p>
+
+
+<h3 id="ExtendingService">Extending the Service class</h3>
+
+<p>As you saw in the previous section, using {@link android.app.IntentService} makes your
+implementation of a started service very simple. If, however, you require your service to
+perform multi-threading (instead of processing start requests through a work queue), then you
+can extend the {@link android.app.Service} class to handle each intent.</p>
+
+<p>For comparison, the following example code is an implementation of the {@link
+android.app.Service} class that performs the exact same work as the example above using {@link
+android.app.IntentService}. That is, for each start request, it uses a worker thread to perform the
+job and processes only one request at a time.</p>
+
+<pre>
+public class HelloService extends Service {
+  private Looper mServiceLooper;
+  private ServiceHandler mServiceHandler;
+
+  // Handler that receives messages from the thread
+  private final class ServiceHandler extends Handler {
+      public ServiceHandler(Looper looper) {
+          super(looper);
+      }
+      &#64;Override
+      public void handleMessage(Message msg) {
+          // Normally we would do some work here, like download a file.
+          // For our sample, we just sleep for 5 seconds.
+          long endTime = System.currentTimeMillis() + 5*1000;
+          while (System.currentTimeMillis() &lt; endTime) {
+              synchronized (this) {
+                  try {
+                      wait(endTime - System.currentTimeMillis());
+                  } catch (Exception e) {
+                  }
+              }
+          }
+          // Stop the service using the startId, so that we don't stop
+          // the service in the middle of handling another job
+          stopSelf(msg.arg1);
+      }
+  }
+
+  &#64;Override
+  public void onCreate() {
+    // Start up the thread running the service.  Note that we create a
+    // separate thread because the service normally runs in the process's
+    // main thread, which we don't want to block.  We also make it
+    // background priority so CPU-intensive work will not disrupt our UI.
+    HandlerThread thread = new HandlerThread("ServiceStartArguments",
+            Process.THREAD_PRIORITY_BACKGROUND);
+    thread.start();
+    
+    // Get the HandlerThread's Looper and use it for our Handler 
+    mServiceLooper = thread.getLooper();
+    mServiceHandler = new ServiceHandler(mServiceLooper);
+  }
+
+  &#64;Override
+  public int onStartCommand(Intent intent, int flags, int startId) {
+      Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
+
+      // For each start request, send a message to start a job and deliver the
+      // start ID so we know which request we're stopping when we finish the job
+      Message msg = mServiceHandler.obtainMessage();
+      msg.arg1 = startId;
+      mServiceHandler.sendMessage(msg);
+      
+      // If we get killed, after returning from here, restart
+      return START_STICKY;
+  }
+
+  &#64;Override
+  public IBinder onBind(Intent intent) {
+      // We don't provide binding, so return null
+      return null;
+  }
+  
+  &#64;Override
+  public void onDestroy() {
+    Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show(); 
+  }
+}
+</pre>
+
+<p>As you can see, it's a lot more work than using {@link android.app.IntentService}.</p>
+
+<p>However, because you handle each call to {@link android.app.Service#onStartCommand
+onStartCommand()} yourself, you can perform multiple requests simultaneously. That's not what
+this example does, but if that's what you want, then you can create a new thread for each
+request and run them right away (instead of waiting for the previous request to finish).</p>
+
+<p>Notice that the {@link android.app.Service#onStartCommand onStartCommand()} method must return an
+integer. The integer is a value that describes how the system should continue the service in the
+event that the system kills it (as discussed above, the default implementation for {@link
+android.app.IntentService} handles this for you, though you are able to modify it). The return value
+from {@link android.app.Service#onStartCommand onStartCommand()} must be one of the following
+constants:</p>
+
+<dl>
+  <dt>{@link android.app.Service#START_NOT_STICKY}</dt>
+    <dd>If the system kills the service after {@link android.app.Service#onStartCommand
+onStartCommand()} returns, <em>do not</em> recreate the service, unless there are pending
+intents to deliver. This is the safest option to avoid running your service when not necessary
+and when your application can simply restart any unfinished jobs.</dd>
+  <dt>{@link android.app.Service#START_STICKY}</dt>
+    <dd>If the system kills the service after {@link android.app.Service#onStartCommand
+onStartCommand()} returns, recreate the service and call {@link
+android.app.Service#onStartCommand onStartCommand()}, but <em>do not</em> redeliver the last intent.
+Instead, the system calls {@link android.app.Service#onStartCommand onStartCommand()} with a
+null intent, unless there were pending intents to start the service, in which case,
+those intents are delivered. This is suitable for media players (or similar services) that are not
+executing commands, but running indefinitely and waiting for a job.</dd>
+  <dt>{@link android.app.Service#START_REDELIVER_INTENT}</dt>
+    <dd>If the system kills the service after {@link android.app.Service#onStartCommand
+onStartCommand()} returns, recreate the service and call {@link
+android.app.Service#onStartCommand onStartCommand()} with the last intent that was delivered to the
+service. Any pending intents are delivered in turn. This is suitable for services that are
+actively performing a job that should be immediately resumed, such as downloading a file.</dd>
+</dl>
+<p>For more details about these return values, see the linked reference documentation for each
+constant.</p>
+
+
+
+<h3 id="StartingAService">Starting a Service</h3>
+
+<p>You can start a service from an activity or other application component by passing an
+{@link android.content.Intent} (specifying the service to start) to {@link
+android.content.Context#startService startService()}. The Android system calls the service's {@link
+android.app.Service#onStartCommand onStartCommand()} method and passes it the {@link
+android.content.Intent}. (You should never call {@link android.app.Service#onStartCommand
+onStartCommand()} directly.)</p>
+
+<p>For example, an activity can start the example service in the previous section ({@code
+HelloSevice}) using an explicit intent with {@link android.content.Context#startService
+startService()}:</p>
+
+<pre>
+Intent intent = new Intent(this, HelloService.class);
+startService(intent);
+</pre>
+
+<p>The {@link android.content.Context#startService startService()} method returns immediately and
+the Android system calls the service's {@link android.app.Service#onStartCommand
+onStartCommand()} method. If the service is not already running, the system first calls {@link
+android.app.Service#onCreate onCreate()}, then calls {@link android.app.Service#onStartCommand
+onStartCommand()}.</p>
+
+<p>If the service does not also provide binding, the intent delivered with {@link
+android.content.Context#startService startService()} is the only mode of communication between the
+application component and the service. However, if you want the service to send a result back, then
+the client that starts the service can create a {@link android.app.PendingIntent} for a broadcast
+(with {@link android.app.PendingIntent#getBroadcast getBroadcast()}) and deliver it to the service
+in the {@link android.content.Intent} that starts the service. The service can then use the
+broadcast to deliver a result.</p>
+
+<p>Multiple requests to start the service result in multiple corresponding calls to the service's
+{@link android.app.Service#onStartCommand onStartCommand()}. However, only one request to stop
+the service (with {@link android.app.Service#stopSelf stopSelf()} or {@link
+android.content.Context#stopService stopService()}) is required to stop it.</p>
+
+
+<h3 id="Stopping">Stopping a service</h3>
+
+<p>A started service must manage its own lifecycle. That is, the system does not stop or
+destroy the service unless it must recover system memory and the service
+continues to run after {@link android.app.Service#onStartCommand onStartCommand()} returns. So,
+the service must stop itself by calling {@link android.app.Service#stopSelf stopSelf()} or another
+component can stop it by calling {@link android.content.Context#stopService stopService()}.</p>
+
+<p>Once requested to stop with {@link android.app.Service#stopSelf stopSelf()} or {@link
+android.content.Context#stopService stopService()}, the system destroys the service as soon as
+possible.</p>
+
+<p>However, if your service handles multiple requests to {@link
+android.app.Service#onStartCommand onStartCommand()} concurrently, then you shouldn't stop the
+service when you're done processing a start request, because you might have since received a new
+start request (stopping at the end of the first request would terminate the second one). To avoid
+this problem, you can use {@link android.app.Service#stopSelf(int)} to ensure that your request to
+stop the service is always based on the most recent start request. That is, when you call {@link
+android.app.Service#stopSelf(int)}, you pass the ID of the start request (the <code>startId</code>
+delivered to {@link android.app.Service#onStartCommand onStartCommand()}) to which your stop request
+corresponds. Then if the service received a new start request before you were able to call {@link
+android.app.Service#stopSelf(int)}, then the ID will not match and the service will not stop.</p>
+
+<p class="caution"><strong>Caution:</strong> It's important that your application stops its services
+when it's done working, to avoid wasting system resources and consuming battery power. If necessary,
+other components can stop the service by calling {@link
+android.content.Context#stopService stopService()}. Even if you enable binding for the service,
+you must always stop the service yourself if it ever received a call to {@link
+android.app.Service#onStartCommand onStartCommand()}.</p>
+
+<p>For more information about the lifecycle of a service, see the section below about <a
+href="#Lifecycle">Managing the Lifecycle of a Service</a>.</p>
+
+
+
+<h2 id="CreatingBoundService">Creating a Bound Service</h2>
+
+<p>A bound service is one that allows application components to bind to it by calling {@link
+android.content.Context#bindService bindService()} in order to create a long-standing connection
+(and generally does not allow components to <em>start</em> it by calling {@link
+android.content.Context#startService startService()}).</p>
+
+<p>You should create a bound service when you want to interact with the service from activities
+and other components in your application or to expose some of your application's functionality to
+other applications, through interprocess communication (IPC).</p>
+
+<p>To create a bound service, you must implement the {@link
+android.app.Service#onBind onBind()} callback method to return an {@link android.os.IBinder} that
+defines the interface for communication with the service. Other application components can then call
+{@link android.content.Context#bindService bindService()} to retrieve the interface and
+begin calling methods on the service. The service lives only to serve the application component that
+is bound to it, so when there are no components bound to the service, the system destroys it
+(you do <em>not</em> need to stop a bound service in the way you must when the service is started
+through {@link android.app.Service#onStartCommand onStartCommand()}).</p>
+
+<p>To create a bound service, the first thing you must do is define the interface that specifies
+how a client can communicate with the service. This interface between the service
+and a client must be an implementation of {@link android.os.IBinder} and is what your service must
+return from the {@link android.app.Service#onBind
+onBind()} callback method. Once the client receives the {@link android.os.IBinder}, it can begin
+interacting with the service through that interface.</p>
+
+<p>Multiple clients can bind to the service at once. When a client is done interacting with the
+service, it calls {@link android.content.Context#unbindService unbindService()} to unbind. Once
+there are no clients bound to the service, the system destroys the service.</p>
+
+<p>There are multiple ways to implement a bound service and the implementation is more
+complicated than a started service, so the bound service discussion appears in a separate
+document about <a
+href="{@docRoot}guide/topics/fundamentals/bound-services.html">Bound Services</a>.</p>
+
+
+
+<h2 id="Notifications">Sending Notifications to the User</h2>
+
+<p>Once running, a service can notify the user of events using <a
+href="{@docRoot}guide/topics/ui/notifiers/toasts.html">Toast Notifications</a> or <a
+href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a>.</p>
+
+<p>A toast notification is a message that appears on the surface of the current window for a
+moment then disappears, while a status bar notification provides an icon in the status bar with a
+message, which the user can select in order to take an action (such as start an activity).</p>
+
+<p>Usually, a status bar notification is the best technique when some background work has completed
+(such as a file completed
+downloading) and the user can now act on it. When the user selects the notification from the
+expanded view, the notification can start an activity (such as to view the downloaded file).</p>
+
+<p>See the <a
+href="{@docRoot}guide/topics/ui/notifiers/toasts.html">Toast Notifications</a> or <a
+href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a>
+developer guides for more information.</p>
+
+
+
+<h2 id="Foreground">Running a Service in the Foreground</h2>
+
+<p>A foreground service is a service that's considered to be something the
+user is actively aware of and thus not a candidate for the system to kill when low on memory. A 
+foreground service must provide a notification for the status bar, which is placed under the
+"Ongoing" heading, which means that the notification cannot be dismissed unless the service is
+either stopped or removed from the foreground.</p>
+
+<p>For example, a music player that plays music from a service should be set to run in the
+foreground, because the user it explicitly aware
+of its operation. The notification in the status bar might indicate the current song and allow
+the user to launch an activity to interact with the music player.</p>
+
+<p>To request that your service run in the foreground, call {@link
+android.app.Service#startForeground startForeground()}. This method takes two parameters: an integer
+that uniquely identifies the notification and the {@link
+android.app.Notification} for the status bar. For example:</p>
+
+<pre>
+Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
+        System.currentTimeMillis());
+Intent notificationIntent = new Intent(this, ExampleActivity.class);
+PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
+notification.setLatestEventInfo(this, getText(R.string.notification_title),
+        getText(R.string.notification_message), pendingIntent);
+startForeground(ONGOING_NOTIFICATION, notification);
+</pre>
+
+
+<p>To remove the service from the foreground, call {@link
+android.app.Service#stopForeground stopForeground()}. This method takes a boolean, indicating
+whether to remove the status bar notification as well. This method does <em>not</em> stop the
+service. However, if you stop the service while it's still running in the foreground, then the
+notification is also removed.</p>
+
+<p class="note"><strong>Note:</strong> The methods {@link
+android.app.Service#startForeground startForeground()} and {@link
+android.app.Service#stopForeground stopForeground()} were introduced in Android 2.0 (API Level
+5). In order to run your service in the foreground on older versions of the platform, you must
+use the previous {@code setForeground()} method&mdash;see the {@link
+android.app.Service#startForeground startForeground()} documentation for information about how
+to provide backward compatibility.</p>
+
+<p>For more information about notifications, see <a
+href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Creating Status Bar
+Notifications</a>.</p>
+
+
+
+<h2 id="Lifecycle">Managing the Lifecycle of a Service</h2>
+
+<p>The lifecycle of a service is much simpler than that of an activity. However, it's even more important
+that you pay close attention to how your service is created and destroyed, because a service
+can run in the background without the user being aware.</p>
+
+<p>The service lifecycle&mdash;from when it's created to when it's destroyed&mdash;can follow two
+different paths:</p>
+
+<ul>
+<li>A started service
+  <p>The service is created when another component calls {@link
+android.content.Context#startService startService()}. The service then runs indefinitely and must
+stop itself by calling {@link
+android.app.Service#stopSelf() stopSelf()}. Another component can also stop the
+service by calling {@link android.content.Context#stopService
+stopService()}. When the service is stopped, the system destroys it..</p></li>
+
+<li>A bound service
+  <p>The service is created when another component (a client) calls {@link
+android.content.Context#bindService bindService()}. The client then communicates with the service
+through an {@link android.os.IBinder} interface. The client can close the connection by calling
+{@link android.content.Context#unbindService unbindService()}. Multiple clients can bind to
+the same service and when all of them unbind, the system destroys the service. (The service
+does <em>not</em> need to stop itself.)</p></li>
+</ul>
+
+<p>These two paths are not entirely separate. That is, you can bind to a service that was already
+started with {@link android.content.Context#startService startService()}. For example, a background
+music service could be started by calling {@link android.content.Context#startService
+startService()} with an {@link android.content.Intent} that identifies the music to play. Later,
+possibly when the user wants to exercise some control over the player or get information about the
+current song, an activity can bind to the service by calling {@link
+android.content.Context#bindService bindService()}. In cases like this, {@link
+android.content.Context#stopService stopService()} or {@link android.app.Service#stopSelf
+stopSelf()} does not actually stop the service until all clients unbind. </p>
+
+
+<h3 id="LifecycleCallbacks">Implementing the lifecycle callbacks</h3>
+
+<p>Like an activity, a service has lifecycle callback methods that you can implement to monitor
+changes in the service's state and perform work at the appropriate times. The following skeleton
+service demonstrates each of the lifecycle methods:</p>
+
+
+<div class="figure" style="width:432px">
+<img src="{@docRoot}images/service_lifecycle.png" alt="" />
+<p class="img-caption"><strong>Figure 2.</strong> The service lifecycle. The diagram on the left
+shows the lifecycle when the service is created with {@link android.content.Context#startService
+startService()} and the diagram on the right shows the lifecycle when the service is created
+with {@link android.content.Context#bindService bindService()}.</p>
+</div>
+
+<pre>
+public class ExampleService extends Service {
+    int mStartMode;       // indicates how to behave if the service is killed
+    IBinder mBinder;      // interface for clients that bind
+    boolean mAllowRebind; // indicates whether onRebind should be used
+
+    &#64;Override
+    public void {@link android.app.Service#onCreate onCreate}() {
+        // The service is being created
+    }
+    &#64;Override
+    public int {@link android.app.Service#onStartCommand onStartCommand}(Intent intent, int flags, int startId) {
+        // The service is starting, due to a call to {@link android.content.Context#startService startService()}
+        return <em>mStartMode</em>;
+    }
+    &#64;Override
+    public IBinder {@link android.app.Service#onBind onBind}(Intent intent) {
+        // A client is binding to the service with {@link android.content.Context#bindService bindService()}
+        return <em>mBinder</em>;
+    }
+    &#64;Override
+    public boolean {@link android.app.Service#onUnbind onUnbind}(Intent intent) {
+        // All clients have unbound with {@link android.content.Context#unbindService unbindService()}
+        return <em>mAllowRebind</em>;
+    }
+    &#64;Override
+    public void {@link android.app.Service#onRebind onRebind}(Intent intent) {
+        // A client is binding to the service with {@link android.content.Context#bindService bindService()},
+        // after onUnbind() has already been called
+    }
+    &#64;Override
+    public void {@link android.app.Service#onDestroy onDestroy}() {
+        // The service is no longer used and is being destroyed
+    }
+}
+</pre>
+
+<p class="note"><strong>Note:</strong> Unlike the activity lifecycle callback methods, you are
+<em>not</em> required to call the superclass implementation of these callback methods.</p>
+
+<p>By implementing these methods, you can monitor two nested loops of the service's lifecycle: </p>
+
+<ul>
+<li>The <strong>entire lifetime</strong> of a service happens between the time {@link
+android.app.Service#onCreate onCreate()} is called and the time {@link
+android.app.Service#onDestroy} returns. Like an activity, a service does its initial setup in
+{@link android.app.Service#onCreate onCreate()} and releases all remaining resources in {@link
+android.app.Service#onDestroy onDestroy()}.  For example, a
+music playback service could create the thread where the music will be played in {@link
+android.app.Service#onCreate onCreate()}, then stop the thread in {@link
+android.app.Service#onDestroy onDestroy()}.
+
+<p>The {@link android.app.Service#onCreate onCreate()} and {@link android.app.Service#onDestroy
+onDestroy()} methods are called for all services, whether
+they're created by {@link android.content.Context#startService startService()} or {@link
+android.content.Context#bindService bindService()}.</p></li>
+
+<li>The <strong>active lifetime</strong> of a service begins with a call to either {@link
+android.app.Service#onStartCommand onStartCommand()} or {@link android.app.Service#onBind onBind()}.
+Each method is handed the {@link
+android.content.Intent} that was passed to either {@link android.content.Context#startService
+startService()} or {@link android.content.Context#bindService bindService()}, respectively.
+<p>If the service is started, the active lifetime ends the same time that the entire lifetime
+ends (the service is still active even after {@link android.app.Service#onStartCommand
+onStartCommand()} returns). If the service is bound, the active lifetime ends when {@link
+android.app.Service#onUnbind onUnbind()} returns.</p>
+</li>
+</ul>
+
+<p class="note"><strong>Note:</strong> Although a started service is stopped by a call to
+either {@link android.app.Service#stopSelf stopSelf()} or {@link
+android.content.Context#stopService stopService()}, there is not a respective callback for the
+service (there's no {@code onStop()} callback). So, unless the service is bound to a client,
+the system destroys it when the service is stopped&mdash;{@link
+android.app.Service#onDestroy onDestroy()} is the only callback received.</p>
+
+<p>Figure 2 illustrates the typical callback methods for a service. Although the figure separates
+services that are created by {@link android.content.Context#startService startService()} from those
+created by {@link android.content.Context#bindService bindService()}, keep
+in mind that any service, no matter how it's started, can potentially allow clients to bind to it.
+So, a service that was initially started with {@link android.app.Service#onStartCommand
+onStartCommand()} (by a client calling {@link android.content.Context#startService startService()})
+can still receive a call to {@link android.app.Service#onBind onBind()} (when a client calls
+{@link android.content.Context#bindService bindService()}).</p>
+
+<p>For more information about creating a service that provides binding, see the <a
+href="{@docRoot}guide/topics/fundamentals/bound-services.html">Bound Services</a> document,
+which includes more information about the {@link android.app.Service#onRebind onRebind()}
+callback method in the section about <a
+href="{@docRoot}guide/topics/fundamentals/bound-services.html#Lifecycle">Managing the Lifecycle of
+a Bound Service</a>.</p>
+
+
+
+<h2>Beginner's Path</h2>
+
+<p>To learn how to query data from the system or other applications (such as contacts or media
+stored on the device), continue with the <b><a
+href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a></b>
+document.</p>
diff --git a/docs/html/images/fundamentals/service_binding_tree_lifecycle.png b/docs/html/images/fundamentals/service_binding_tree_lifecycle.png
new file mode 100644
index 0000000..46d2df5
--- /dev/null
+++ b/docs/html/images/fundamentals/service_binding_tree_lifecycle.png
Binary files differ
diff --git a/docs/html/images/service_lifecycle.png b/docs/html/images/service_lifecycle.png
index 0748db2..f9602f8 100644
--- a/docs/html/images/service_lifecycle.png
+++ b/docs/html/images/service_lifecycle.png
Binary files differ
diff --git a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
index 39a7dd2..94a8488 100644
--- a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
@@ -207,7 +207,7 @@
     @Override
     public ConstantState getConstantState() {
         if (mState.canConstantState()) {
-            mState.mChangingConfigurations = super.getChangingConfigurations();
+            mState.mChangingConfigurations = getChangingConfigurations();
             return mState;
         }
         return null;
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index 032244f..2c09ddc 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -439,7 +439,7 @@
 
     @Override
     public final ConstantState getConstantState() {
-        mBitmapState.mChangingConfigurations = super.getChangingConfigurations();
+        mBitmapState.mChangingConfigurations = getChangingConfigurations();
         return mBitmapState;
     }
 
diff --git a/graphics/java/android/graphics/drawable/ClipDrawable.java b/graphics/java/android/graphics/drawable/ClipDrawable.java
index 0d44591..b333e01 100644
--- a/graphics/java/android/graphics/drawable/ClipDrawable.java
+++ b/graphics/java/android/graphics/drawable/ClipDrawable.java
@@ -232,7 +232,7 @@
     @Override
     public ConstantState getConstantState() {
         if (mClipState.canConstantState()) {
-            mClipState.mChangingConfigurations = super.getChangingConfigurations();
+            mClipState.mChangingConfigurations = getChangingConfigurations();
             return mClipState;
         }
         return null;
diff --git a/graphics/java/android/graphics/drawable/ColorDrawable.java b/graphics/java/android/graphics/drawable/ColorDrawable.java
index 4d560be..4418e02 100644
--- a/graphics/java/android/graphics/drawable/ColorDrawable.java
+++ b/graphics/java/android/graphics/drawable/ColorDrawable.java
@@ -149,7 +149,7 @@
 
     @Override
     public ConstantState getConstantState() {
-        mState.mChangingConfigurations = super.getChangingConfigurations();
+        mState.mChangingConfigurations = getChangingConfigurations();
         return mState;
     }
 
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 0a580eb..a9414e8 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -389,7 +389,7 @@
     @Override
     public ConstantState getConstantState() {
         if (mDrawableContainerState.canConstantState()) {
-            mDrawableContainerState.mChangingConfigurations = super.getChangingConfigurations();
+            mDrawableContainerState.mChangingConfigurations = getChangingConfigurations();
             return mDrawableContainerState;
         }
         return null;
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index da8bb1b..65c6ccf 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -861,7 +861,7 @@
     
     @Override
     public ConstantState getConstantState() {
-        mGradientState.mChangingConfigurations = super.getChangingConfigurations();
+        mGradientState.mChangingConfigurations = getChangingConfigurations();
         return mGradientState;
     }
 
diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java
index 3a74dfd..231234c 100644
--- a/graphics/java/android/graphics/drawable/InsetDrawable.java
+++ b/graphics/java/android/graphics/drawable/InsetDrawable.java
@@ -241,7 +241,7 @@
     @Override
     public ConstantState getConstantState() {
         if (mInsetState.canConstantState()) {
-            mInsetState.mChangingConfigurations = super.getChangingConfigurations();
+            mInsetState.mChangingConfigurations = getChangingConfigurations();
             return mInsetState;
         }
         return null;
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 84da170..49dbbca 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -557,7 +557,7 @@
     @Override
     public ConstantState getConstantState() {
         if (mLayerState.canConstantState()) {
-            mLayerState.mChangingConfigurations = super.getChangingConfigurations();
+            mLayerState.mChangingConfigurations = getChangingConfigurations();
             return mLayerState;
         }
         return null;
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index 35b8319..a5175c5 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -323,7 +323,7 @@
     
     @Override
     public ConstantState getConstantState() {
-        mNinePatchState.mChangingConfigurations = super.getChangingConfigurations();
+        mNinePatchState.mChangingConfigurations = getChangingConfigurations();
         return mNinePatchState;
     }
 
diff --git a/graphics/java/android/graphics/drawable/RotateDrawable.java b/graphics/java/android/graphics/drawable/RotateDrawable.java
index 212ddfa..4f74b37 100644
--- a/graphics/java/android/graphics/drawable/RotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/RotateDrawable.java
@@ -192,7 +192,7 @@
     @Override
     public ConstantState getConstantState() {
         if (mState.canConstantState()) {
-            mState.mChangingConfigurations = super.getChangingConfigurations();
+            mState.mChangingConfigurations = getChangingConfigurations();
             return mState;
         }
         return null;
diff --git a/graphics/java/android/graphics/drawable/ScaleDrawable.java b/graphics/java/android/graphics/drawable/ScaleDrawable.java
index 055576d..a7ed0d0 100644
--- a/graphics/java/android/graphics/drawable/ScaleDrawable.java
+++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java
@@ -241,7 +241,7 @@
     @Override
     public ConstantState getConstantState() {
         if (mScaleState.canConstantState()) {
-            mScaleState.mChangingConfigurations = super.getChangingConfigurations();
+            mScaleState.mChangingConfigurations = getChangingConfigurations();
             return mScaleState;
         }
         return null;
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index 92252fc..cb8774d 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -356,7 +356,7 @@
     
     @Override
     public ConstantState getConstantState() {
-        mShapeState.mChangingConfigurations = super.getChangingConfigurations();
+        mShapeState.mChangingConfigurations = getChangingConfigurations();
         return mShapeState;
     }
 
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index b15121a..579f314 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -503,7 +503,7 @@
      * Creates a renderscript allocation with the size specified by
      * the type and no mipmaps generated by default
      *
-     * @param rs
+     * @param rs Context to which the allocation will belong.
      * @param type renderscript type describing data layout
      * @param usage bit field specifying how the allocation is
      *              utilized
@@ -519,7 +519,7 @@
      * the size specified by the type and no mipmaps generated by
      * default
      *
-     * @param rs
+     * @param rs Context to which the allocation will belong.
      * @param type renderscript type describing data layout
      *
      * @return allocation
@@ -532,7 +532,7 @@
      * Creates a renderscript allocation with a specified number of
      * given elements
      *
-     * @param rs
+     * @param rs Context to which the allocation will belong.
      * @param e describes what each element of an allocation is
      * @param count specifies the number of element in the allocation
      * @param usage bit field specifying how the allocation is
@@ -558,7 +558,7 @@
      * Creates a renderscript allocation with a specified number of
      * given elements
      *
-     * @param rs
+     * @param rs Context to which the allocation will belong.
      * @param e describes what each element of an allocation is
      * @param count specifies the number of element in the allocation
      *
@@ -598,7 +598,7 @@
     /**
      * Creates a renderscript allocation from a bitmap
      *
-     * @param rs
+     * @param rs Context to which the allocation will belong.
      * @param b bitmap source for the allocation data
      * @param mips specifies desired mipmap behaviour for the
      *             allocation
@@ -625,7 +625,7 @@
      * Creates a non-mipmapped renderscript allocation to use as a
      * graphics texture
      *
-     * @param rs
+     * @param rs Context to which the allocation will belong.
      * @param b bitmap source for the allocation data
      *
      * @return renderscript allocation containing bitmap data
@@ -641,7 +641,7 @@
      * horizontal list of cube faces. Each individual face must be
      * the same size and power of 2
      *
-     * @param rs
+     * @param rs Context to which the allocation will belong.
      * @param b bitmap with cubemap faces layed out in the following
      *          format: right, left, top, bottom, front, back
      * @param mips specifies desired mipmap behaviour for the cubemap
@@ -690,7 +690,7 @@
      * of cube faces. Each individual face must be the same size and
      * power of 2
      *
-     * @param rs
+     * @param rs Context to which the allocation will belong.
      * @param b bitmap with cubemap faces layed out in the following
      *          format: right, left, top, bottom, front, back
      *
@@ -708,7 +708,7 @@
      * the cube faces. All the faces must be the same size and
      * power of 2
      *
-     * @param rs
+     * @param rs Context to which the allocation will belong.
      * @param xpos cubemap face in the positive x direction
      * @param xneg cubemap face in the negative x direction
      * @param ypos cubemap face in the positive y direction
@@ -776,7 +776,7 @@
      * the cube faces. All the faces must be the same size and
      * power of 2
      *
-     * @param rs
+     * @param rs Context to which the allocation will belong.
      * @param xpos cubemap face in the positive x direction
      * @param xneg cubemap face in the negative x direction
      * @param ypos cubemap face in the positive y direction
@@ -803,7 +803,7 @@
      * Creates a renderscript allocation from the bitmap referenced
      * by resource id
      *
-     * @param rs
+     * @param rs Context to which the allocation will belong.
      * @param res application resources
      * @param id resource id to load the data from
      * @param mips specifies desired mipmap behaviour for the
@@ -831,7 +831,7 @@
      * Creates a non-mipmapped renderscript allocation to use as a
      * graphics texture from the bitmap referenced by resource id
      *
-     * @param rs
+     * @param rs Context to which the allocation will belong.
      * @param res application resources
      * @param id resource id to load the data from
      *
@@ -850,7 +850,7 @@
      * Creates a renderscript allocation containing string data
      * encoded in UTF-8 format
      *
-     * @param rs
+     * @param rs Context to which the allocation will belong.
      * @param str string to create the allocation from
      * @param usage bit field specifying how the allocaiton is
      *              utilized
diff --git a/graphics/java/android/renderscript/FileA3D.java b/graphics/java/android/renderscript/FileA3D.java
index 90d102c..fe3971a 100644
--- a/graphics/java/android/renderscript/FileA3D.java
+++ b/graphics/java/android/renderscript/FileA3D.java
@@ -28,22 +28,22 @@
 import android.util.TypedValue;
 
 /**
+ * FileA3D allows users to load renderscript objects from files
+ * or resources stored on disk. It could be used to load items
+ * such as 3d geometry data converted a renderscript format from
+ * content creation tools. Currently only meshes are supported
+ * in FileA3D.
+ *
+ * When successfully loaded, FileA3D will contain a list of
+ * index entries for all the objects stored inside it.
  *
  **/
 public class FileA3D extends BaseObj {
 
-    // This will go away in the clean up pass,
-    // trying to avoid multiproject submits
-    public enum ClassID {
-
-        UNKNOWN,
-        MESH;
-
-        public static ClassID toClassID(int intID) {
-            return ClassID.values()[intID];
-        }
-    }
-
+    /**
+    * Specifies what renderscript object type is contained within
+    * the FileA3D IndexEntry
+    **/
     public enum EntryType {
 
         UNKNOWN (0),
@@ -59,34 +59,48 @@
         }
     }
 
-    // Read only class with index entries
+    /**
+    * IndexEntry contains information about one of the renderscript
+    * objects inside the file's index. It could be used to query the
+    * object's type and name and load the object itself if
+    * necessary.
+    */
     public static class IndexEntry {
         RenderScript mRS;
         int mIndex;
         int mID;
         String mName;
-        ClassID mClassID;
         EntryType mEntryType;
         BaseObj mLoadedObj;
 
+        /**
+        * @return name of a renderscript object the index entry
+        *         describes
+        */
         public String getName() {
             return mName;
         }
 
-        public ClassID getClassID() {
-            return mClassID;
-        }
-
+        /**
+        * @return type of a renderscript object the index entry
+        *         describes
+        */
         public EntryType getEntryType() {
             return mEntryType;
         }
 
+        /**
+        * @return renderscript object described by the entry
+        */
         public BaseObj getObject() {
             mRS.validate();
             BaseObj obj = internalCreate(mRS, this);
             return obj;
         }
 
+        /**
+        * @return renderscript mesh object described by the entry
+        */
         public Mesh getMesh() {
             return (Mesh)getObject();
         }
@@ -122,7 +136,6 @@
             mID = id;
             mName = name;
             mEntryType = type;
-            mClassID = mEntryType == EntryType.MESH ? ClassID.MESH : ClassID.UNKNOWN;
             mLoadedObj = null;
         }
     }
@@ -152,6 +165,9 @@
         }
     }
 
+    /**
+    * @return the numberof objects stored inside a FileA3D
+    */
     public int getIndexEntryCount() {
         if(mFileEntries == null) {
             return 0;
@@ -159,6 +175,12 @@
         return mFileEntries.length;
     }
 
+    /**
+    * Returns an index entry from the list of all objects inside
+    * FileA3D
+    *
+    * @param index number of the entry from the list to return
+    */
     public IndexEntry getIndexEntry(int index) {
         if(getIndexEntryCount() == 0 || index < 0 || index >= mFileEntries.length) {
             return null;
@@ -166,6 +188,14 @@
         return mFileEntries[index];
     }
 
+    /**
+    * Creates a FileA3D object from an asset stored on disk
+    *
+    * @param rs Context to which the object will belong.
+    * @param mgr asset manager used to load asset
+    * @param path location of the file to load
+    *
+    */
     static public FileA3D createFromAsset(RenderScript rs, AssetManager mgr, String path) {
         rs.validate();
         int fileId = rs.nFileA3DCreateFromAsset(mgr, path);
@@ -178,6 +208,13 @@
         return fa3d;
     }
 
+    /**
+    * Creates a FileA3D object from a file stored on disk
+    *
+    * @param rs Context to which the object will belong.
+    * @param path location of the file to load
+    *
+    */
     static public FileA3D createFromFile(RenderScript rs, String path) {
         int fileId = rs.nFileA3DCreateFromFile(path);
 
@@ -189,10 +226,25 @@
         return fa3d;
     }
 
+    /**
+    * Creates a FileA3D object from a file stored on disk
+    *
+    * @param rs Context to which the object will belong.
+    * @param path location of the file to load
+    *
+    */
     static public FileA3D createFromFile(RenderScript rs, File path) {
         return createFromFile(rs, path.getAbsolutePath());
     }
 
+    /**
+    * Creates a FileA3D object from an application resource
+    *
+    * @param rs Context to which the object will belong.
+    * @param res resource manager used for loading
+    * @param id resource to create FileA3D from
+    *
+    */
     static public FileA3D createFromResource(RenderScript rs, Resources res, int id) {
 
         rs.validate();
diff --git a/graphics/java/android/renderscript/Mesh.java b/graphics/java/android/renderscript/Mesh.java
index f1f1237..fcf8178 100644
--- a/graphics/java/android/renderscript/Mesh.java
+++ b/graphics/java/android/renderscript/Mesh.java
@@ -172,7 +172,7 @@
 
         /**
         * Creates builder object
-        * @param rs
+        * @param rs Context to which the mesh will belong.
         * @param usage specifies how the mesh allocations are to be
         *              handled, whether they need to be uploaded to a
         *              buffer on the gpu, maintain a cpu copy, etc
@@ -512,7 +512,7 @@
         public static final int TEXTURE_0 = 0x0100;
 
         /**
-        * @param rs
+        * @param rs Context to which the mesh will belong.
         * @param vtxSize specifies whether the vertex is a float2 or
         *                float3
         * @param flags bitfield that is a combination of COLOR, NORMAL,
diff --git a/graphics/java/android/renderscript/Program.java b/graphics/java/android/renderscript/Program.java
index fdd138c..323225f 100644
--- a/graphics/java/android/renderscript/Program.java
+++ b/graphics/java/android/renderscript/Program.java
@@ -33,10 +33,10 @@
  *
  **/
 public class Program extends BaseObj {
-    public static final int MAX_INPUT = 8;
-    public static final int MAX_OUTPUT = 8;
-    public static final int MAX_CONSTANT = 8;
-    public static final int MAX_TEXTURE = 8;
+    static final int MAX_INPUT = 8;
+    static final int MAX_OUTPUT = 8;
+    static final int MAX_CONSTANT = 8;
+    static final int MAX_TEXTURE = 8;
 
     /**
      *
diff --git a/graphics/java/android/renderscript/ProgramFragment.java b/graphics/java/android/renderscript/ProgramFragment.java
index 14c0c01..333880d 100644
--- a/graphics/java/android/renderscript/ProgramFragment.java
+++ b/graphics/java/android/renderscript/ProgramFragment.java
@@ -36,7 +36,7 @@
         /**
          * Create a builder object.
          *
-         * @param rs
+         * @param rs Context to which the program will belong.
          */
         public Builder(RenderScript rs) {
             super(rs);
diff --git a/graphics/java/android/renderscript/ProgramFragmentFixedFunction.java b/graphics/java/android/renderscript/ProgramFragmentFixedFunction.java
index 663bc9f..1af31f8 100644
--- a/graphics/java/android/renderscript/ProgramFragmentFixedFunction.java
+++ b/graphics/java/android/renderscript/ProgramFragmentFixedFunction.java
@@ -194,7 +194,7 @@
         /**
          * Creates a builder for fixed function fragment program
          *
-         * @param rs
+         * @param rs Context to which the program will belong.
          */
         public Builder(RenderScript rs) {
             mRS = rs;
diff --git a/graphics/java/android/renderscript/ProgramStore.java b/graphics/java/android/renderscript/ProgramStore.java
index d79900e..9128f9b 100644
--- a/graphics/java/android/renderscript/ProgramStore.java
+++ b/graphics/java/android/renderscript/ProgramStore.java
@@ -149,7 +149,7 @@
     *  - incoming pixels override the value stored in the color
     *    buffer if it passes the depth test
     *
-    *  @param rs
+    *  @param rs Context to which the program will belong.
     **/
     public static ProgramStore BLEND_NONE_DEPTH_TEST(RenderScript rs) {
         if(rs.mProgramStore_BLEND_NONE_DEPTH_TEST == null) {
@@ -170,7 +170,7 @@
     *  - incoming pixels override the value stored in the color
     *    buffer
     *
-    *  @param rs
+    *  @param rs Context to which the program will belong.
     **/
     public static ProgramStore BLEND_NONE_DEPTH_NONE(RenderScript rs) {
         if(rs.mProgramStore_BLEND_NONE_DEPTH_NO_DEPTH == null) {
@@ -194,7 +194,7 @@
     *    following formula
     *  Final.RGB = Source.RGB * Source.A + Dest.RGB * (1 - Source.A)
     *
-    *  @param rs
+    *  @param rs Context to which the program will belong.
     **/
     public static ProgramStore BLEND_ALPHA_DEPTH_TEST(RenderScript rs) {
         if(rs.mProgramStore_BLEND_ALPHA_DEPTH_TEST == null) {
@@ -216,7 +216,7 @@
     *    (Dest) using the following formula
     *  Final.RGB = Source.RGB * Source.A + Dest.RGB * (1 - Source.A)
     *
-    *  @param rs
+    *  @param rs Context to which the program will belong.
     **/
     public static ProgramStore BLEND_ALPHA_DEPTH_NONE(RenderScript rs) {
         if(rs.mProgramStore_BLEND_ALPHA_DEPTH_NO_DEPTH == null) {
diff --git a/graphics/java/android/renderscript/ProgramVertex.java b/graphics/java/android/renderscript/ProgramVertex.java
index 7ba8b82..a965b81 100644
--- a/graphics/java/android/renderscript/ProgramVertex.java
+++ b/graphics/java/android/renderscript/ProgramVertex.java
@@ -46,7 +46,7 @@
         /**
          * Create a builder object.
          *
-         * @param rs
+         * @param rs Context to which the program will belong.
          */
         public Builder(RenderScript rs) {
             super(rs);
diff --git a/graphics/java/android/renderscript/ProgramVertexFixedFunction.java b/graphics/java/android/renderscript/ProgramVertexFixedFunction.java
index b9537c7..666c7ec 100644
--- a/graphics/java/android/renderscript/ProgramVertexFixedFunction.java
+++ b/graphics/java/android/renderscript/ProgramVertexFixedFunction.java
@@ -105,7 +105,7 @@
         /**
          * Creates a builder for fixed function vertex program
          *
-         * @param rs
+         * @param rs Context to which the program will belong.
          */
         public Builder(RenderScript rs) {
             mRS = rs;
@@ -196,9 +196,9 @@
         private FieldPacker mIOBuffer;
 
         /**
-        * Creates buffer to store fixed function emulation matrices
+        * Creates a buffer to store fixed function emulation matrices
         *
-        * @param rs
+        * @param rs Context to which the allocation will belong.
         **/
         public Constants(RenderScript rs) {
             Type constInputType = ProgramVertexFixedFunction.Builder.getConstantInputType(rs);
diff --git a/graphics/java/android/renderscript/Sampler.java b/graphics/java/android/renderscript/Sampler.java
index 57a9889..c656d75 100644
--- a/graphics/java/android/renderscript/Sampler.java
+++ b/graphics/java/android/renderscript/Sampler.java
@@ -56,7 +56,7 @@
      * Retrieve a sampler with min and mag set to nearest and wrap modes set to
      * clamp.
      *
-     * @param rs
+     * @param rs Context to which the sampler will belong.
      *
      * @return Sampler
      */
@@ -76,7 +76,7 @@
      * Retrieve a sampler with min and mag set to linear and wrap modes set to
      * clamp.
      *
-     * @param rs
+     * @param rs Context to which the sampler will belong.
      *
      * @return Sampler
      */
@@ -96,7 +96,7 @@
      * Retrieve a sampler with ag set to linear, min linear mipmap linear, and
      * to and wrap modes set to clamp.
      *
-     * @param rs
+     * @param rs Context to which the sampler will belong.
      *
      * @return Sampler
      */
@@ -116,7 +116,7 @@
      * Retrieve a sampler with min and mag set to nearest and wrap modes set to
      * wrap.
      *
-     * @param rs
+     * @param rs Context to which the sampler will belong.
      *
      * @return Sampler
      */
@@ -136,7 +136,7 @@
      * Retrieve a sampler with min and mag set to nearest and wrap modes set to
      * wrap.
      *
-     * @param rs
+     * @param rs Context to which the sampler will belong.
      *
      * @return Sampler
      */
@@ -156,7 +156,7 @@
      * Retrieve a sampler with ag set to linear, min linear mipmap linear, and
      * to and wrap modes set to wrap.
      *
-     * @param rs
+     * @param rs Context to which the sampler will belong.
      *
      * @return Sampler
      */
diff --git a/libs/hwui/Debug.h b/libs/hwui/Debug.h
index a194cbe..bdd8e73 100644
--- a/libs/hwui/Debug.h
+++ b/libs/hwui/Debug.h
@@ -47,4 +47,7 @@
 // Turn on to display debug info about the layer renderer
 #define DEBUG_LAYER_RENDERER 0
 
+// Turn on to dump display list state
+#define DEBUG_DISPLAY_LIST 0
+
 #endif // ANDROID_HWUI_DEBUG_H
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 57df976..747543f 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -81,6 +81,39 @@
 // Display list
 ///////////////////////////////////////////////////////////////////////////////
 
+const char* DisplayList::OP_NAMES[] = {
+    "AcquireContext",
+    "ReleaseContext",
+    "Save",
+    "Restore",
+    "RestoreToCount",
+    "SaveLayer",
+    "SaveLayerAlpha",
+    "Translate",
+    "Rotate",
+    "Scale",
+    "SetMatrix",
+    "ConcatMatrix",
+    "ClipRect",
+    "DrawDisplayList",
+    "DrawLayer",
+    "DrawBitmap",
+    "DrawBitmapMatrix",
+    "DrawBitmapRect",
+    "DrawPatch",
+    "DrawColor",
+    "DrawRect",
+    "DrawPath",
+    "DrawLines",
+    "DrawText",
+    "ResetShader",
+    "SetupShader",
+    "ResetColorFilter",
+    "SetupColorFilter",
+    "ResetShadow",
+    "SetupShadow"
+};
+
 DisplayList::DisplayList(const DisplayListRenderer& recorder) {
     initFromDisplayListRenderer(recorder);
 }
@@ -95,10 +128,10 @@
     }
     mBitmapResources.clear();
 
-    for (size_t i = 0; i < mShaderResources.size(); i++) {
-        caches.resourceCache.decrementRefcount(mShaderResources.itemAt(i));
+    for (size_t i = 0; i < mShaders.size(); i++) {
+        delete mShaders.itemAt(i);
     }
-    mShaderResources.clear();
+    mShaders.clear();
 
     for (size_t i = 0; i < mPaints.size(); i++) {
         delete mPaints.itemAt(i);
@@ -146,11 +179,9 @@
         caches.resourceCache.incrementRefcount(resource);
     }
 
-    const Vector<SkiaShader*> &shaderResources = recorder.getShaderResources();
-    for (size_t i = 0; i < shaderResources.size(); i++) {
-        SkiaShader* resource = shaderResources.itemAt(i);
-        mShaderResources.add(resource);
-        caches.resourceCache.incrementRefcount(resource);
+    const Vector<SkiaShader*> &shaders = recorder.getShaders();
+    for (size_t i = 0; i < shaders.size(); i++) {
+        mShaders.add(shaders.itemAt(i));
     }
 
     const Vector<SkPaint*> &paints = recorder.getPaints();
@@ -173,14 +204,25 @@
     mPathHeap = NULL;
 }
 
-void DisplayList::replay(OpenGLRenderer& renderer) {
+void DisplayList::replay(OpenGLRenderer& renderer, uint32_t level) {
     TextContainer text;
     mReader.rewind();
 
-    int saveCount = renderer.getSaveCount() - 1;
+#if DEBUG_DISPLAY_LIST
+    uint32_t count = (level + 1) * 2;
+    char indent[count + 1];
+    for (uint32_t i = 0; i < count; i++) {
+        indent[i] = ' ';
+    }
+    indent[count] = '\0';
+    DISPLAY_LIST_LOGD("%sStart display list (%p)", (char*) indent + 2, this);
+#endif
 
+    int saveCount = renderer.getSaveCount() - 1;
     while (!mReader.eof()) {
         int op = mReader.readInt();
+        DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
+
         switch (op) {
             case AcquireContext: {
                 renderer.acquireContext();
@@ -238,7 +280,7 @@
             }
             break;
             case DrawDisplayList: {
-                renderer.drawDisplayList(getDisplayList());
+                renderer.drawDisplayList(getDisplayList(), level + 1);
             }
             break;
             case DrawLayer: {
@@ -326,6 +368,8 @@
             break;
         }
     }
+
+    DISPLAY_LIST_LOGD("%sDone", (char*) indent + 2);
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -361,14 +405,10 @@
     }
     mBitmapResources.clear();
 
-    for (size_t i = 0; i < mShaderResources.size(); i++) {
-        SkiaShader* resource = mShaderResources.itemAt(i);
-        caches.resourceCache.decrementRefcount(resource);
-    }
-    mShaderResources.clear();
-
     mPaints.clear();
     mPaintMap.clear();
+    mShaders.clear();
+    mShaderMap.clear();
     mMatrices.clear();
 }
 
@@ -482,7 +522,7 @@
     return OpenGLRenderer::clipRect(left, top, right, bottom, op);
 }
 
-void DisplayListRenderer::drawDisplayList(DisplayList* displayList) {
+void DisplayListRenderer::drawDisplayList(DisplayList* displayList, uint32_t level) {
     addOp(DisplayList::DrawDisplayList);
     addDisplayList(displayList);
 }
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 0822725..f183473 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -39,6 +39,13 @@
 #define MIN_WRITER_SIZE 16384
 #define HEAP_BLOCK_SIZE 4096
 
+// Debug
+#if DEBUG_DISPLAY_LIST
+    #define DISPLAY_LIST_LOGD(...) LOGD(__VA_ARGS__)
+#else
+    #define DISPLAY_LIST_LOGD(...)
+#endif
+
 ///////////////////////////////////////////////////////////////////////////////
 // Helpers
 ///////////////////////////////////////////////////////////////////////////////
@@ -78,8 +85,10 @@
     DisplayList(const DisplayListRenderer& recorder);
     ~DisplayList();
 
+    // IMPORTANT: Update the intialization of OP_NAMES in the .cpp file
+    //            when modifying this file
     enum Op {
-        AcquireContext,
+        AcquireContext = 0,
         ReleaseContext,
         Save,
         Restore,
@@ -108,12 +117,14 @@
         ResetColorFilter,
         SetupColorFilter,
         ResetShadow,
-        SetupShadow
+        SetupShadow,
     };
 
+    static const char* OP_NAMES[];
+
     void initFromDisplayListRenderer(const DisplayListRenderer& recorder);
 
-    void replay(OpenGLRenderer& renderer);
+    void replay(OpenGLRenderer& renderer, uint32_t level = 0);
 
 private:
     void init();
@@ -195,11 +206,11 @@
     PathHeap* mPathHeap;
 
     Vector<SkBitmap*> mBitmapResources;
-    Vector<SkiaShader*> mShaderResources;
     Vector<SkiaColorFilter*> mFilterResources;
 
     Vector<SkPaint*> mPaints;
     Vector<SkMatrix*> mMatrices;
+    Vector<SkiaShader*> mShaders;
 
     mutable SkFlattenableReadBuffer mReader;
 
@@ -245,7 +256,7 @@
 
     bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
 
-    void drawDisplayList(DisplayList* displayList);
+    void drawDisplayList(DisplayList* displayList, uint32_t level = 0);
     void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
     void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
     void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
@@ -280,8 +291,8 @@
         return mBitmapResources;
     }
 
-    const Vector<SkiaShader*>& getShaderResources() const {
-        return mShaderResources;
+    const Vector<SkiaShader*>& getShaders() const {
+        return mShaders;
     }
 
     const Vector<SkPaint*>& getPaints() const {
@@ -355,12 +366,12 @@
     }
 
     inline void addPaint(SkPaint* paint) {
-        if (paint == NULL) {
+        if (!paint) {
             addInt((int) NULL);
             return;
         }
 
-        SkPaint *paintCopy =  mPaintMap.valueFor(paint);
+        SkPaint* paintCopy =  mPaintMap.valueFor(paint);
         if (paintCopy == NULL || paintCopy->getGenerationID() != paint->getGenerationID()) {
             paintCopy = new SkPaint(*paint);
             mPaintMap.add(paint, paintCopy);
@@ -395,10 +406,20 @@
     }
 
     inline void addShader(SkiaShader* shader) {
-        addInt((int) shader);
-        mShaderResources.add(shader);
-        Caches& caches = Caches::getInstance();
-        caches.resourceCache.incrementRefcount(shader);
+        if (!shader) {
+            addInt((int) NULL);
+            return;
+        }
+
+        SkiaShader* shaderCopy = mShaderMap.valueFor(shader);
+        // TODO: We also need to handle generation ID changes in compose shaders
+        if (shaderCopy == NULL || shaderCopy->getGenerationId() != shader->getGenerationId()) {
+            shaderCopy = shader->copy();
+            mShaderMap.add(shader, shaderCopy);
+            mShaders.add(shaderCopy);
+        }
+
+        addInt((int) shaderCopy);
     }
 
     inline void addColorFilter(SkiaColorFilter* colorFilter) {
@@ -411,11 +432,14 @@
     SkChunkAlloc mHeap;
 
     Vector<SkBitmap*> mBitmapResources;
-    Vector<SkiaShader*> mShaderResources;
     Vector<SkiaColorFilter*> mFilterResources;
 
     Vector<SkPaint*> mPaints;
     DefaultKeyedVector<SkPaint*, SkPaint*> mPaintMap;
+
+    Vector<SkiaShader*> mShaders;
+    DefaultKeyedVector<SkiaShader*, SkiaShader*> mShaderMap;
+
     Vector<SkMatrix*> mMatrices;
 
     PathHeap* mPathHeap;
diff --git a/libs/hwui/OpenGLDebugRenderer.cpp b/libs/hwui/OpenGLDebugRenderer.cpp
index f71e5d6..29bcde8 100644
--- a/libs/hwui/OpenGLDebugRenderer.cpp
+++ b/libs/hwui/OpenGLDebugRenderer.cpp
@@ -48,7 +48,7 @@
     return OpenGLRenderer::saveLayer(left, top, right, bottom, p, flags);
 }
 
-void OpenGLDebugRenderer::drawDisplayList(DisplayList* displayList) {
+void OpenGLDebugRenderer::drawDisplayList(DisplayList* displayList, uint32_t level) {
     mPrimitivesCount++;
     StopWatch w("drawDisplayList");
     OpenGLRenderer::drawDisplayList(displayList);
diff --git a/libs/hwui/OpenGLDebugRenderer.h b/libs/hwui/OpenGLDebugRenderer.h
index 1cef267..aefa7bf 100644
--- a/libs/hwui/OpenGLDebugRenderer.h
+++ b/libs/hwui/OpenGLDebugRenderer.h
@@ -40,7 +40,7 @@
     int saveLayer(float left, float top, float right, float bottom,
             SkPaint* p, int flags);
 
-    void drawDisplayList(DisplayList* displayList);
+    void drawDisplayList(DisplayList* displayList, uint32_t level = 0);
     void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
     void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
     void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 7f7deec..f005573 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -697,12 +697,12 @@
     if ((mSnapshot->flags & Snapshot::kFlagFboTarget) && mSnapshot->region) {
         Rect bounds(left, top, right, bottom);
         transform.mapRect(bounds);
-        bounds.intersect(*mSnapshot->clipRect);
-        bounds.snapToPixelBoundaries();
-
-        android::Rect dirty(bounds.left, bounds.top, bounds.right, bounds.bottom);
-        if (!dirty.isEmpty()) {
-            mSnapshot->region->orSelf(dirty);
+        if (bounds.intersect(*mSnapshot->clipRect)) {
+            bounds.snapToPixelBoundaries();
+            android::Rect dirty(bounds.left, bounds.top, bounds.right, bounds.bottom);
+            if (!dirty.isEmpty()) {
+                mSnapshot->region->orSelf(dirty);
+            }
         }
     }
 #endif
@@ -713,12 +713,12 @@
 #if RENDER_LAYERS_AS_REGIONS
     if ((mSnapshot->flags & Snapshot::kFlagFboTarget) && mSnapshot->region) {
         Rect bounds(left, top, right, bottom);
-        bounds.intersect(*mSnapshot->clipRect);
-        bounds.snapToPixelBoundaries();
-
-        android::Rect dirty(bounds.left, bounds.top, bounds.right, bounds.bottom);
-        if (!dirty.isEmpty()) {
-            mSnapshot->region->orSelf(dirty);
+        if (bounds.intersect(*mSnapshot->clipRect)) {
+            bounds.snapToPixelBoundaries();
+            android::Rect dirty(bounds.left, bounds.top, bounds.right, bounds.bottom);
+            if (!dirty.isEmpty()) {
+                mSnapshot->region->orSelf(dirty);
+            }
         }
     }
 #endif
@@ -1024,11 +1024,11 @@
 // Drawing
 ///////////////////////////////////////////////////////////////////////////////
 
-void OpenGLRenderer::drawDisplayList(DisplayList* displayList) {
+void OpenGLRenderer::drawDisplayList(DisplayList* displayList, uint32_t level) {
     // All the usual checks and setup operations (quickReject, setupDraw, etc.)
     // will be performed by the display list itself
     if (displayList) {
-        displayList->replay(*this);
+        displayList->replay(*this, level);
     }
 }
 
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index da27dac..8cec8f1 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -94,7 +94,7 @@
     bool quickReject(float left, float top, float right, float bottom);
     virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
 
-    virtual void drawDisplayList(DisplayList* displayList);
+    virtual void drawDisplayList(DisplayList* displayList, uint32_t level = 0);
     virtual void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
     virtual void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
     virtual void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 590a9d7..a1783df 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -47,10 +47,22 @@
 // Base shader
 ///////////////////////////////////////////////////////////////////////////////
 
+void SkiaShader::copyFrom(const SkiaShader& shader) {
+    mType = shader.mType;
+    mKey = shader.mKey;
+    mTileX = shader.mTileX;
+    mTileY = shader.mTileY;
+    mBlend = shader.mBlend;
+    mUnitMatrix = shader.mUnitMatrix;
+    mShaderMatrix = shader.mShaderMatrix;
+    mGenerationId = shader.mGenerationId;
+}
+
 SkiaShader::SkiaShader(Type type, SkShader* key, SkShader::TileMode tileX,
         SkShader::TileMode tileY, SkMatrix* matrix, bool blend):
         mType(type), mKey(key), mTileX(tileX), mTileY(tileY), mBlend(blend) {
     setMatrix(matrix);
+    mGenerationId = 0;
 }
 
 SkiaShader::~SkiaShader() {
@@ -90,6 +102,13 @@
     updateLocalMatrix(matrix);
 }
 
+SkiaShader* SkiaBitmapShader::copy() {
+    SkiaBitmapShader* copy = new SkiaBitmapShader();
+    copy->copyFrom(*this);
+    copy->mBitmap = mBitmap;
+    return copy;
+}
+
 void SkiaBitmapShader::describe(ProgramDescription& description, const Extensions& extensions) {
     Texture* texture = mTextureCache->get(mBitmap);
     if (!texture) return;
@@ -183,6 +202,16 @@
     delete[] mPositions;
 }
 
+SkiaShader* SkiaLinearGradientShader::copy() {
+    SkiaLinearGradientShader* copy = new SkiaLinearGradientShader();
+    copy->copyFrom(*this);
+    copy->mBounds = mBounds;
+    copy->mColors = mColors;
+    copy->mPositions = mPositions;
+    copy->mCount = mCount;
+    return copy;
+}
+
 void SkiaLinearGradientShader::describe(ProgramDescription& description,
         const Extensions& extensions) {
     description.hasGradient = true;
@@ -238,6 +267,15 @@
     updateLocalMatrix(matrix);
 }
 
+SkiaShader* SkiaCircularGradientShader::copy() {
+    SkiaCircularGradientShader* copy = new SkiaCircularGradientShader();
+    copy->copyFrom(*this);
+    copy->mColors = mColors;
+    copy->mPositions = mPositions;
+    copy->mCount = mCount;
+    return copy;
+}
+
 void SkiaCircularGradientShader::describe(ProgramDescription& description,
         const Extensions& extensions) {
     description.hasGradient = true;
@@ -276,6 +314,15 @@
     delete[] mPositions;
 }
 
+SkiaShader* SkiaSweepGradientShader::copy() {
+    SkiaSweepGradientShader* copy = new SkiaSweepGradientShader();
+    copy->copyFrom(*this);
+    copy->mColors = mColors;
+    copy->mPositions = mPositions;
+    copy->mCount = mCount;
+    return copy;
+}
+
 void SkiaSweepGradientShader::describe(ProgramDescription& description,
         const Extensions& extensions) {
     description.hasGradient = true;
@@ -318,6 +365,15 @@
         NULL, first->blend() || second->blend()), mFirst(first), mSecond(second), mMode(mode) {
 }
 
+SkiaShader* SkiaComposeShader::copy() {
+    SkiaComposeShader* copy = new SkiaComposeShader();
+    copy->copyFrom(*this);
+    copy->mFirst = mFirst;
+    copy->mSecond = mSecond;
+    copy->mMode = mMode;
+    return copy;
+}
+
 void SkiaComposeShader::set(TextureCache* textureCache, GradientCache* gradientCache) {
     SkiaShader::set(textureCache, gradientCache);
     mFirst->set(textureCache, gradientCache);
diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h
index 6702129..1ebde38 100644
--- a/libs/hwui/SkiaShader.h
+++ b/libs/hwui/SkiaShader.h
@@ -56,6 +56,9 @@
             SkMatrix* matrix, bool blend);
     virtual ~SkiaShader();
 
+    virtual SkiaShader* copy() = 0;
+    void copyFrom(const SkiaShader& shader);
+
     virtual void describe(ProgramDescription& description, const Extensions& extensions);
     virtual void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
             GLuint* textureUnit);
@@ -81,8 +84,13 @@
             const Snapshot& snapshot) {
     }
 
+    uint32_t getGenerationId() {
+        return mGenerationId;
+    }
+
     void setMatrix(SkMatrix* matrix) {
         updateLocalMatrix(matrix);
+        mGenerationId++;
     }
 
     void updateLocalMatrix(const SkMatrix* matrix) {
@@ -97,6 +105,9 @@
     void computeScreenSpaceMatrix(mat4& screenSpace, const mat4& modelView);
 
 protected:
+    SkiaShader() {
+    }
+
     /**
      * The appropriate texture unit must have been activated prior to invoking
      * this method.
@@ -114,6 +125,9 @@
 
     mat4 mUnitMatrix;
     mat4 mShaderMatrix;
+
+private:
+    uint32_t mGenerationId;
 }; // struct SkiaShader
 
 
@@ -127,6 +141,7 @@
 struct SkiaBitmapShader: public SkiaShader {
     SkiaBitmapShader(SkBitmap* bitmap, SkShader* key, SkShader::TileMode tileX,
             SkShader::TileMode tileY, SkMatrix* matrix, bool blend);
+    SkiaShader* copy();
 
     void describe(ProgramDescription& description, const Extensions& extensions);
     void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
@@ -134,6 +149,9 @@
     void updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot);
 
 private:
+    SkiaBitmapShader() {
+    }
+
     /**
      * This method does not work for n == 0.
      */
@@ -154,6 +172,7 @@
     SkiaLinearGradientShader(float* bounds, uint32_t* colors, float* positions, int count,
             SkShader* key, SkShader::TileMode tileMode, SkMatrix* matrix, bool blend);
     ~SkiaLinearGradientShader();
+    SkiaShader* copy();
 
     void describe(ProgramDescription& description, const Extensions& extensions);
     void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
@@ -161,6 +180,9 @@
     void updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot);
 
 private:
+    SkiaLinearGradientShader() {
+    }
+
     float* mBounds;
     uint32_t* mColors;
     float* mPositions;
@@ -174,6 +196,7 @@
     SkiaSweepGradientShader(float x, float y, uint32_t* colors, float* positions, int count,
             SkShader* key, SkMatrix* matrix, bool blend);
     ~SkiaSweepGradientShader();
+    SkiaShader* copy();
 
     virtual void describe(ProgramDescription& description, const Extensions& extensions);
     void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
@@ -183,6 +206,8 @@
 protected:
     SkiaSweepGradientShader(Type type, float x, float y, uint32_t* colors, float* positions,
             int count, SkShader* key, SkShader::TileMode tileMode, SkMatrix* matrix, bool blend);
+    SkiaSweepGradientShader() {
+    }
 
     uint32_t* mColors;
     float* mPositions;
@@ -195,8 +220,13 @@
 struct SkiaCircularGradientShader: public SkiaSweepGradientShader {
     SkiaCircularGradientShader(float x, float y, float radius, uint32_t* colors, float* positions,
             int count, SkShader* key,SkShader::TileMode tileMode, SkMatrix* matrix, bool blend);
+    SkiaShader* copy();
 
     void describe(ProgramDescription& description, const Extensions& extensions);
+
+private:
+    SkiaCircularGradientShader() {
+    }
 }; // struct SkiaCircularGradientShader
 
 /**
@@ -204,6 +234,7 @@
  */
 struct SkiaComposeShader: public SkiaShader {
     SkiaComposeShader(SkiaShader* first, SkiaShader* second, SkXfermode::Mode mode, SkShader* key);
+    SkiaShader* copy();
 
     void set(TextureCache* textureCache, GradientCache* gradientCache);
 
@@ -212,6 +243,9 @@
             GLuint* textureUnit);
 
 private:
+    SkiaComposeShader() {
+    }
+
     SkiaShader* mFirst;
     SkiaShader* mSecond;
     SkXfermode::Mode mMode;
diff --git a/libs/rs/Android.mk b/libs/rs/Android.mk
index d8d70c6..3835852 100644
--- a/libs/rs/Android.mk
+++ b/libs/rs/Android.mk
@@ -23,17 +23,17 @@
 # TODO: This should go into build/core/config.mk
 RSG_GENERATOR:=$(LOCAL_BUILT_MODULE)
 
-include $(CLEAR_VARS)
-input_data_file := $(LOCAL_PATH)/rslib.bc
-slangdata_output_var_name := rs_runtime_lib_bc
-LOCAL_MODULE := librslib_rt
+# include $(CLEAR_VARS)
+# input_data_file := $(LOCAL_PATH)/rslib.bc
+# slangdata_output_var_name := rs_runtime_lib_bc
+# LOCAL_MODULE := librslib_rt
 
-LOCAL_PRELINK_MODULE := false
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+# LOCAL_PRELINK_MODULE := false
+# LOCAL_MODULE_CLASS := STATIC_LIBRARIES
 
-LOCAL_MODULE_TAGS := optional
-include frameworks/compile/slang/SlangData.mk
-include $(BUILD_STATIC_LIBRARY)
+# LOCAL_MODULE_TAGS := optional
+# include frameworks/compile/slang/SlangData.mk
+# include $(BUILD_STATIC_LIBRARY)
 
 # Build render script lib ====================
 
@@ -119,9 +119,10 @@
 
 LOCAL_SHARED_LIBRARIES += libz libcutils libutils libEGL libGLESv1_CM libGLESv2 libui libbcc
 
-LOCAL_STATIC_LIBRARIES := libdex libft2 librslib_rt
+LOCAL_STATIC_LIBRARIES := libdex libft2
 
 LOCAL_C_INCLUDES += external/freetype/include external/zlib dalvik
+LOCAL_C_INCLUDES += frameworks/compile/libbcc/include
 
 LOCAL_LDLIBS := -lpthread -ldl
 LOCAL_MODULE:= libRS
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index bb38825..2e0c491 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -236,6 +236,7 @@
     glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &mGL.mMaxFragmentUniformVectors);
 
     mGL.OES_texture_npot = NULL != strstr((const char *)mGL.mExtensions, "GL_OES_texture_npot");
+    mGL.GL_IMG_texture_npot = NULL != strstr((const char *)mGL.mExtensions, "GL_IMG_texture_npot");
     mGL.GL_NV_texture_npot_2D_mipmap = NULL != strstr((const char *)mGL.mExtensions, "GL_NV_texture_npot_2D_mipmap");
     mGL.EXT_texture_max_aniso = 1.0f;
     bool hasAniso = NULL != strstr((const char *)mGL.mExtensions, "GL_EXT_texture_filter_anisotropic");
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
index df275bc..9f94f26 100644
--- a/libs/rs/rsContext.h
+++ b/libs/rs/rsContext.h
@@ -205,6 +205,7 @@
     mutable const ObjectBase * mObjHead;
 
     bool ext_OES_texture_npot() const {return mGL.OES_texture_npot;}
+    bool ext_GL_IMG_texture_npot() const {return mGL.GL_IMG_texture_npot;}
     bool ext_GL_NV_texture_npot_2D_mipmap() const {return mGL.GL_NV_texture_npot_2D_mipmap;}
     float ext_texture_max_aniso() const {return mGL.EXT_texture_max_aniso; }
     uint32_t getMaxFragmentTextures() const {return mGL.mMaxFragmentTextureImageUnits;}
@@ -249,6 +250,7 @@
         int32_t mMaxVertexTextureUnits;
 
         bool OES_texture_npot;
+        bool GL_IMG_texture_npot;
         bool GL_NV_texture_npot_2D_mipmap;
         float EXT_texture_max_aniso;
     } mGL;
diff --git a/libs/rs/rsContextHostStub.h b/libs/rs/rsContextHostStub.h
index c22647f..8cfb38b 100644
--- a/libs/rs/rsContextHostStub.h
+++ b/libs/rs/rsContextHostStub.h
@@ -119,11 +119,12 @@
     mutable const ObjectBase * mObjHead;
 
     bool ext_OES_texture_npot() const {return mGL.OES_texture_npot;}
-    bool ext_GL_NV_texture_npot_2D_mipmap() const {return false;}
-    float ext_texture_max_aniso() const {return 1.0f;}
+    bool ext_GL_NV_texture_npot_2D_mipmap() const {return mGL.GL_NV_texture_npot_2D_mipmap;}
+    float ext_texture_max_aniso() const {return mGL.EXT_texture_max_aniso; }
     uint32_t getMaxFragmentTextures() const {return mGL.mMaxFragmentTextureImageUnits;}
     uint32_t getMaxFragmentUniformVectors() const {return mGL.mMaxFragmentUniformVectors;}
     uint32_t getMaxVertexUniformVectors() const {return mGL.mMaxVertexUniformVectors;}
+    uint32_t getMaxVertexAttributes() const {return mGL.mMaxVertexAttribs;}
 
 protected:
 
@@ -147,6 +148,8 @@
         int32_t mMaxVertexTextureUnits;
 
         bool OES_texture_npot;
+        bool GL_NV_texture_npot_2D_mipmap;
+        float EXT_texture_max_aniso;
     } mGL;
 
 };
diff --git a/libs/rs/rsSampler.cpp b/libs/rs/rsSampler.cpp
index e2757df..c80aecc 100644
--- a/libs/rs/rsSampler.cpp
+++ b/libs/rs/rsSampler.cpp
@@ -77,8 +77,20 @@
     GLenum target = (GLenum)tex->getGLTarget();
 
     if (!rsc->ext_OES_texture_npot() && tex->getType()->getIsNp2()) {
-        if (tex->getHasGraphicsMipmaps() && rsc->ext_GL_NV_texture_npot_2D_mipmap()) {
-            glTexParameteri(target, GL_TEXTURE_MIN_FILTER, trans[mMinFilter]);
+        if (tex->getHasGraphicsMipmaps() &&
+            (rsc->ext_GL_NV_texture_npot_2D_mipmap() || rsc->ext_GL_IMG_texture_npot())) {
+            if (rsc->ext_GL_NV_texture_npot_2D_mipmap()) {
+                glTexParameteri(target, GL_TEXTURE_MIN_FILTER, trans[mMinFilter]);
+            } else {
+                switch (trans[mMinFilter]) {
+                case GL_LINEAR_MIPMAP_LINEAR:
+                    glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
+                    break;
+                default:
+                    glTexParameteri(target, GL_TEXTURE_MIN_FILTER, trans[mMinFilter]);
+                    break;
+                }
+            }
         } else {
             glTexParameteri(target, GL_TEXTURE_MIN_FILTER, transNP[mMinFilter]);
         }
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
index 5dd976a..872e7a6 100644
--- a/libs/rs/rsScriptC.cpp
+++ b/libs/rs/rsScriptC.cpp
@@ -17,7 +17,6 @@
 #include "rsContext.h"
 #include "rsScriptC.h"
 #include "rsMatrix.h"
-#include "../../compile/libbcc/include/bcc/bcc.h"
 #include "utils/Timers.h"
 #include "utils/StopWatch.h"
 extern "C" {
@@ -35,6 +34,64 @@
     Context * rsc = tls->mContext; \
     ScriptC * sc = (ScriptC *) tls->mScript
 
+// Input: cacheDir
+// Input: resName
+// Input: extName
+//
+// Note: cacheFile = resName + extName
+//
+// Output: Returns cachePath == cacheDir + cacheFile
+char *genCacheFileName(const char *cacheDir,
+                       const char *resName,
+                       const char *extName) {
+    char cachePath[512];
+    char cacheFile[sizeof(cachePath)];
+    const size_t kBufLen = sizeof(cachePath) - 1;
+
+    cacheFile[0] = '\0';
+    // Note: resName today is usually something like
+    //       "/com.android.fountain:raw/fountain"
+    if (resName[0] != '/') {
+        // Get the absolute path of the raw/***.bc file.
+
+        // Generate the absolute path.  This doesn't do everything it
+        // should, e.g. if resName is "./out/whatever" it doesn't crunch
+        // the leading "./" out because this if-block is not triggered,
+        // but it'll make do.
+        //
+        if (getcwd(cacheFile, kBufLen) == NULL) {
+            LOGE("Can't get CWD while opening raw/***.bc file\n");
+            return NULL;
+        }
+        // Append "/" at the end of cacheFile so far.
+        strncat(cacheFile, "/", kBufLen);
+    }
+
+    // cacheFile = resName + extName
+    //
+    strncat(cacheFile, resName, kBufLen);
+    if (extName != NULL) {
+        // TODO(srhines): strncat() is a bit dangerous
+        strncat(cacheFile, extName, kBufLen);
+    }
+
+    // Turn the path into a flat filename by replacing
+    // any slashes after the first one with '@' characters.
+    char *cp = cacheFile + 1;
+    while (*cp != '\0') {
+        if (*cp == '/') {
+            *cp = '@';
+        }
+        cp++;
+    }
+
+    // Tack on the file name for the actual cache file path.
+    strncpy(cachePath, cacheDir, kBufLen);
+    strncat(cachePath, cacheFile, kBufLen);
+
+    LOGV("Cache file for '%s' '%s' is '%s'\n", resName, extName, cachePath);
+    return strdup(cachePath);
+}
 
 ScriptC::ScriptC(Context *rsc) : Script(rsc) {
     LOGD(">>>> ScriptC ctor called, obj=%p", this);
@@ -45,7 +102,7 @@
 ScriptC::~ScriptC() {
     LOGD(">>>> ~ScriptC() mBccScript = %p", mBccScript);
     if (mBccScript) {
-        bccDeleteScript(mBccScript);
+        bccDisposeScript(mBccScript);
         LOGD(">>>> ~ScriptC(mBCCScript)");
     }
     free(mEnviroment.mScriptText);
@@ -381,11 +438,11 @@
     mScript.set(new ScriptC(rsc));
 }
 
-static BCCvoid* symbolLookup(BCCvoid* pContext, const BCCchar* name) {
+static void* symbolLookup(void* pContext, char const* name) {
     const ScriptCState::SymbolTable_t *sym;
     ScriptC *s = (ScriptC *)pContext;
     if (!strcmp(name, "__isThreadable")) {
-      return (BCCvoid*) s->mEnviroment.mIsThreadable;
+      return (void*) s->mEnviroment.mIsThreadable;
     } else if (!strcmp(name, "__clearThreadable")) {
       s->mEnviroment.mIsThreadable = false;
       return NULL;
@@ -420,30 +477,33 @@
         bccRegisterSymbolCallback(s->mBccScript, symbolLookup, s);
 
         if (bccReadBC(s->mBccScript,
+                      resName,
                       s->mEnviroment.mScriptText,
-                      s->mEnviroment.mScriptTextLength,
-                      /*deprecated*/ 0, /*deprecated*/ 0,
-                      resName, cacheDir) != 0) {
+                      s->mEnviroment.mScriptTextLength, 0) != 0) {
             LOGE("bcc: FAILS to read bitcode");
             // Handle Fatal Error
         }
 
 #if 0
         if (bccLinkBC(s->mBccScript,
+                      resName,
                       rs_runtime_lib_bc,
-                      rs_runtime_lib_bc_size) != 0) {
+                      rs_runtime_lib_bc_size, 0) != 0) {
             LOGE("bcc: FAILS to link bitcode");
             // Handle Fatal Error
         }
 #endif
+        char *cachePath = genCacheFileName(cacheDir, resName, ".oBCC");
 
-        if (bccPrepareExecutable(s->mBccScript) != 0) {
+        if (bccPrepareExecutable(s->mBccScript, cachePath, 0) != 0) {
             LOGE("bcc: FAILS to prepare executable");
             // Handle Fatal Error
         }
 
-        bccGetScriptLabel(s->mBccScript, "root", (BCCvoid**) &s->mProgram.mRoot);
-        bccGetScriptLabel(s->mBccScript, "init", (BCCvoid**) &s->mProgram.mInit);
+        free(cachePath);
+
+        s->mProgram.mRoot = reinterpret_cast<int (*)()>(bccGetFuncAddr(s->mBccScript, "root"));
+        s->mProgram.mInit = reinterpret_cast<void (*)()>(bccGetFuncAddr(s->mBccScript, "init"));
     }
     LOGV("%p ScriptCState::runCompiler root %p,  init %p", rsc, s->mProgram.mRoot, s->mProgram.mInit);
 
@@ -451,20 +511,20 @@
         s->mProgram.mInit();
     }
 
-    bccGetExportFuncs(s->mBccScript, (BCCsizei*) &s->mEnviroment.mInvokeFunctionCount, 0, NULL);
+    s->mEnviroment.mInvokeFunctionCount = bccGetExportFuncCount(s->mBccScript);
     if (s->mEnviroment.mInvokeFunctionCount <= 0)
         s->mEnviroment.mInvokeFunctions = NULL;
     else {
         s->mEnviroment.mInvokeFunctions = (Script::InvokeFunc_t*) calloc(s->mEnviroment.mInvokeFunctionCount, sizeof(Script::InvokeFunc_t));
-        bccGetExportFuncs(s->mBccScript, NULL, s->mEnviroment.mInvokeFunctionCount, (BCCvoid **) s->mEnviroment.mInvokeFunctions);
+        bccGetExportFuncList(s->mBccScript, s->mEnviroment.mInvokeFunctionCount, (void **) s->mEnviroment.mInvokeFunctions);
     }
 
-    bccGetExportVars(s->mBccScript, (BCCsizei*) &s->mEnviroment.mFieldCount, 0, NULL);
+    s->mEnviroment.mFieldCount = bccGetExportVarCount(s->mBccScript);
     if (s->mEnviroment.mFieldCount <= 0)
         s->mEnviroment.mFieldAddress = NULL;
     else {
         s->mEnviroment.mFieldAddress = (void **) calloc(s->mEnviroment.mFieldCount, sizeof(void *));
-        bccGetExportVars(s->mBccScript, NULL, s->mEnviroment.mFieldCount, (BCCvoid **) s->mEnviroment.mFieldAddress);
+        bccGetExportVarList(s->mBccScript, s->mEnviroment.mFieldCount, (void **) s->mEnviroment.mFieldAddress);
         s->initSlots();
     }
 
@@ -475,63 +535,61 @@
 
     if (s->mProgram.mRoot) {
         const static int pragmaMax = 16;
-        BCCsizei pragmaCount;
-        BCCchar * str[pragmaMax];
-        bccGetPragmas(s->mBccScript, &pragmaCount, pragmaMax, &str[0]);
+        size_t pragmaCount = bccGetPragmaCount(s->mBccScript);
+        char const *keys[pragmaMax];
+        char const *values[pragmaMax];
+        bccGetPragmaList(s->mBccScript, pragmaMax, keys, values);
 
-        for (int ct=0; ct < pragmaCount; ct+=2) {
-            //LOGE("pragme %s %s", str[ct], str[ct+1]);
-            if (!strcmp(str[ct], "version")) {
+        for (size_t i=0; i < pragmaCount; ++i) {
+            //LOGE("pragma %s %s", keys[i], values[i]);
+            if (!strcmp(keys[i], "version")) {
                 continue;
             }
 
-            if (!strcmp(str[ct], "stateVertex")) {
-                if (!strcmp(str[ct+1], "default")) {
+            if (!strcmp(keys[i], "stateVertex")) {
+                if (!strcmp(values[i], "default")) {
                     continue;
                 }
-                if (!strcmp(str[ct+1], "parent")) {
+                if (!strcmp(values[i], "parent")) {
                     s->mEnviroment.mVertex.clear();
                     continue;
                 }
-                LOGE("Unreconized value %s passed to stateVertex", str[ct+1]);
+                LOGE("Unreconized value %s passed to stateVertex", values[i]);
             }
 
-            if (!strcmp(str[ct], "stateRaster")) {
-                if (!strcmp(str[ct+1], "default")) {
+            if (!strcmp(keys[i], "stateRaster")) {
+                if (!strcmp(values[i], "default")) {
                     continue;
                 }
-                if (!strcmp(str[ct+1], "parent")) {
+                if (!strcmp(values[i], "parent")) {
                     s->mEnviroment.mRaster.clear();
                     continue;
                 }
-                LOGE("Unreconized value %s passed to stateRaster", str[ct+1]);
+                LOGE("Unreconized value %s passed to stateRaster", values[i]);
             }
 
-            if (!strcmp(str[ct], "stateFragment")) {
-                if (!strcmp(str[ct+1], "default")) {
+            if (!strcmp(keys[i], "stateFragment")) {
+                if (!strcmp(values[i], "default")) {
                     continue;
                 }
-                if (!strcmp(str[ct+1], "parent")) {
+                if (!strcmp(values[i], "parent")) {
                     s->mEnviroment.mFragment.clear();
                     continue;
                 }
-                LOGE("Unreconized value %s passed to stateFragment", str[ct+1]);
+                LOGE("Unreconized value %s passed to stateFragment", values[i]);
             }
 
-            if (!strcmp(str[ct], "stateStore")) {
-                if (!strcmp(str[ct+1], "default")) {
+            if (!strcmp(keys[i], "stateStore")) {
+                if (!strcmp(values[i], "default")) {
                     continue;
                 }
-                if (!strcmp(str[ct+1], "parent")) {
+                if (!strcmp(values[i], "parent")) {
                     s->mEnviroment.mFragmentStore.clear();
                     continue;
                 }
-                LOGE("Unreconized value %s passed to stateStore", str[ct+1]);
+                LOGE("Unreconized value %s passed to stateStore", values[i]);
             }
-
         }
-
-
     } else {
         LOGE("bcc: FAILS to prepare executable");
         // Handle Fatal Error
diff --git a/libs/rs/rsScriptC.h b/libs/rs/rsScriptC.h
index cd68546..483481e8 100644
--- a/libs/rs/rsScriptC.h
+++ b/libs/rs/rsScriptC.h
@@ -21,9 +21,7 @@
 
 #include "RenderScriptEnv.h"
 
-namespace bcc {
-class Script;
-}
+#include <bcc/bcc.h>
 
 // ---------------------------------------------------------------------------
 namespace android {
@@ -48,7 +46,7 @@
 
     Program_t mProgram;
 
-    bcc::Script* mBccScript;
+    BCCScriptRef mBccScript;
 
     const Allocation *ptrToAllocation(const void *) const;
 
diff --git a/libs/rs/rslib.bc b/libs/rs/rslib.bc
deleted file mode 100644
index 761e765..0000000
--- a/libs/rs/rslib.bc
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_input_methods_item.xml b/packages/SystemUI/res/layout-xlarge/status_bar_input_methods_item.xml
new file mode 100644
index 0000000..3028a42
--- /dev/null
+++ b/packages/SystemUI/res/layout-xlarge/status_bar_input_methods_item.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeight"
+    android:background="@drawable/status_bar_item_background"
+    android:orientation="vertical"
+    android:paddingRight="6dip"
+    android:paddingLeft="6dip"
+    android:paddingTop="5dip"
+    android:paddingBottom="5dip"
+    android:gravity="center_vertical">
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:gravity="center_vertical"
+        android:orientation="horizontal">
+        <LinearLayout
+            android:id="@+id/item_subtype"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:gravity="center_vertical"
+            android:orientation="horizontal"
+            android:background="?android:attr/selectableItemBackground">
+            <RadioButton
+                android:id="@+id/item_radio"
+                android:layout_width="30dip"
+                android:layout_height="wrap_content"
+                android:layout_marginRight="11dip"
+                android:focusable="false"
+                android:clickable="false" />
+            <ImageView
+                android:id="@+id/item_icon"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:scaleType="fitCenter" />
+            <LinearLayout
+                android:orientation="vertical"
+                android:layout_width="0px"
+                android:layout_weight="1"
+                android:layout_height="wrap_content">
+                <TextView
+                    android:id="@+id/item_title"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:textAppearance="?android:attr/textAppearanceMedium"
+                    android:singleLine="true"
+                    android:ellipsize="marquee"
+                    android:layout_marginBottom="2dip" />
+                <TextView
+                    android:id="@+id/item_subtitle"
+                    android:layout_marginTop="-4dip"
+                    android:layout_gravity="center_vertical|left"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:textAppearance="?android:attr/textAppearanceSmall" />
+            </LinearLayout>
+        </LinearLayout>
+        <View
+            android:id="@+id/item_vertical_separator"
+            android:layout_width="2dip"
+            android:layout_height="match_parent"
+            android:layout_marginBottom="5dip"
+            android:background="@android:drawable/divider_horizontal_dark" />
+        <ImageView
+            android:id="@+id/item_settings_icon"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_marginLeft="5dip"
+            android:layout_gravity="center_vertical"
+            android:paddingRight="10dip"
+            android:paddingLeft="10dip"
+            android:src="@drawable/ic_sysbar_quicksettings"
+            android:visibility="visible"
+            android:clickable="true"
+            android:focusable="true"
+            android:background="?android:attr/selectableItemBackground" />
+    </LinearLayout>
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="1dip"
+        android:background="@android:drawable/divider_horizontal_dark" />
+</LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_input_methods_panel.xml b/packages/SystemUI/res/layout-xlarge/status_bar_input_methods_panel.xml
new file mode 100644
index 0000000..c4bca61
--- /dev/null
+++ b/packages/SystemUI/res/layout-xlarge/status_bar_input_methods_panel.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<com.android.systemui.statusbar.tablet.InputMethodsPanel
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_height="match_parent"
+    android:layout_width="match_parent"
+    android:paddingBottom="28dip"
+    android:orientation="vertical">
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1" />
+    <FrameLayout
+        android:id="@+id/glow"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:background="@drawable/recents_blue_glow">
+        <LinearLayout
+            android:layout_width="450dip"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="20dip"
+            android:orientation="vertical"
+            android:background="@*android:drawable/dialog_full_holo_dark">
+            <ScrollView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:overScrollMode="ifContentScrolls"
+                android:layout_marginTop="3dip"
+                android:layout_weight="1">
+                <LinearLayout
+                    android:id="@+id/input_method_menu_list"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:orientation="vertical" />
+            </ScrollView>
+            <TextView
+                android:id="@+id/ime_settings_shortcut"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:minHeight="?android:attr/listPreferredItemHeight"
+                android:background="?android:attr/selectableItemBackground"
+                android:orientation="vertical"
+                android:paddingRight="6dip"
+                android:paddingLeft="30dip"
+                android:paddingTop="5dip"
+                android:paddingBottom="5dip"
+                android:gravity="center_vertical"
+                android:singleLine="true"
+                android:text="@string/status_bar_input_method_settings_configure_input_methods"
+                android:textAppearance="?android:attr/textAppearanceMedium"
+                android:ellipsize="marquee" />
+        </LinearLayout>
+    </FrameLayout>
+</com.android.systemui.statusbar.tablet.InputMethodsPanel>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_notification_row.xml b/packages/SystemUI/res/layout-xlarge/status_bar_notification_row.xml
index 6b12d29..4991a40 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar_notification_row.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar_notification_row.xml
@@ -27,7 +27,7 @@
         <!-- TODO: scaleType should be top-left but ImageView doesn't support that. -->
 
     <com.android.systemui.statusbar.LatestItemView android:id="@+id/content"
-        android:layout_width="wrap_content"
+        android:layout_width="match_parent"
         android:layout_height="64sp"
         android:layout_alignParentTop="true"
         android:layout_toRightOf="@id/large_icon"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index caafbdb..53d06c0 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -109,5 +109,7 @@
     <string name="recent_tasks_app_label">Apps</string>
 
     <!-- Network connection string for Bluetooth Reverse Tethering -->
-    <string name="bluetooth_tethered">Bluetooth tethered"</string>
+    <string name="bluetooth_tethered">Bluetooth tethered</string>
+    <!-- Title of a button to open the settings for input methods [CHAR LIMIT=30] -->
+    <string name="status_bar_input_method_settings_configure_input_methods">Configure input methods</string>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodButton.java
index df4bfa1..69bc161 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodButton.java
@@ -19,11 +19,9 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.graphics.drawable.Drawable;
-import android.os.Handler;
 import android.os.IBinder;
 import android.provider.Settings;
 import android.util.Log;
-import android.util.Slog;
 import android.util.AttributeSet;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodManager;
@@ -31,11 +29,8 @@
 import android.view.View;
 import android.widget.ImageView;
 
-import com.android.server.InputMethodManagerService;
 import com.android.systemui.R;
 
-import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -56,9 +51,6 @@
     // other services we wish to talk to
     private final InputMethodManager mImm;
     private final int mId;
-    // Cache of InputMethodsInfo
-    private final HashMap<String, InputMethodInfo> mInputMethodsInfo =
-            new HashMap<String, InputMethodInfo>();
     private ImageView mIcon;
     private IBinder mToken;
     private boolean mKeyboardVisible = false;
@@ -102,20 +94,6 @@
         refreshStatusIcon();
     }
 
-    private InputMethodInfo getCurrentInputMethodInfo() {
-        String curInputMethodId = Settings.Secure.getString(getContext()
-                .getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
-        if (!mInputMethodsInfo.containsKey(curInputMethodId)) {
-            mInputMethodsInfo.clear();
-            List<InputMethodInfo> imis = mImm.getInputMethodList();
-            for (int i = 0; i < imis.size(); ++i) {
-                InputMethodInfo imi = imis.get(i);
-                mInputMethodsInfo.put(imi.getId(), imi);
-            }
-        }
-        return mInputMethodsInfo.get(curInputMethodId);
-    }
-
     // TODO: Need to show an appropriate drawable for this shortcut button,
     // if there are two or more shortcut input methods contained in this button.
     // And need to add other methods to handle multiple shortcuts as appropriate.
@@ -141,8 +119,7 @@
         final PackageManager pm = getContext().getPackageManager();
         if (imi != null) {
             if (DEBUG) {
-                Log.d(TAG, "Update icons of IME: " + imi.getPackageName() + ","
-                        + subtype.getLocale() + "," + subtype.getMode());
+                Log.d(TAG, "Update icons of IME: " + imi.getPackageName());
             }
             if (subtype != null) {
                 return pm.getDrawable(imi.getPackageName(), subtype.getIconResId(),
@@ -188,25 +165,19 @@
             return;
         }
         if (!needsToShowIMEButton()) {
-            setVisibility(View.INVISIBLE);
+            setVisibility(View.GONE);
             return;
         } else {
             setVisibility(View.VISIBLE);
         }
         Drawable icon = null;
         switch (mId) {
-            case ID_IME_SWITCH_BUTTON:
-                // TODO: Just showing the first shortcut IME subtype for now. Should handle all
-                // shortcuts as appropriate.
-                icon = getSubtypeIcon(getCurrentInputMethodInfo(),
-                        mImm.getCurrentInputMethodSubtype());
-                break;
             case ID_IME_SHORTCUT_BUTTON:
                 icon = getShortcutInputMethodAndSubtypeDrawable();
                 break;
         }
         if (icon == null) {
-            mIcon.setImageResource(R.drawable.ic_sysbar_ime_default);
+            mIcon.setImageResource(R.drawable.ic_sysbar_ime);
         } else {
             mIcon.setImageDrawable(icon);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
new file mode 100644
index 0000000..d4ba693
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/InputMethodsPanel.java
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.tablet;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.os.IBinder;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Pair;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.RadioButton;
+import android.widget.TextView;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+
+import com.android.systemui.R;
+
+public class InputMethodsPanel extends LinearLayout implements StatusBarPanel, OnClickListener {
+    private static final boolean DEBUG = TabletStatusBar.DEBUG;
+    private static final String TAG = "InputMethodsPanel";
+
+    private final InputMethodManager mImm;
+    private final HashMap<InputMethodInfo, List<InputMethodSubtype>>
+            mEnabledInputMethodAndSubtypesCache =
+                    new HashMap<InputMethodInfo, List<InputMethodSubtype>>();
+    private final HashMap<View, Pair<InputMethodInfo, InputMethodSubtype>> mRadioViewAndImiMap =
+            new HashMap<View, Pair<InputMethodInfo, InputMethodSubtype>>();
+    private final PackageManager mPackageManager;
+
+    private Context mContext;
+    private IBinder mToken;
+    private LinearLayout mInputMethodMenuList;
+    private String mEnabledInputMethodAndSubtypesCacheStr;
+    private View mConfigureImeShortcut;
+
+    public InputMethodsPanel(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public InputMethodsPanel(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+        mContext = context;
+        mImm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
+        mPackageManager = context.getPackageManager();
+    }
+
+    @Override
+    public void onFinishInflate() {
+        mInputMethodMenuList = (LinearLayout) findViewById(R.id.input_method_menu_list);
+        mConfigureImeShortcut = ((View) findViewById(R.id.ime_settings_shortcut));
+        mConfigureImeShortcut.setOnClickListener(this);
+        // TODO: If configurations for IME are not changed, do not update
+        // by checking onConfigurationChanged.
+        updateUiElements();
+    }
+
+    @Override
+    public boolean isInContentArea(int x, int y) {
+        return false;
+    }
+
+    @Override
+    protected void onVisibilityChanged(View changedView, int visibility) {
+        super.onVisibilityChanged(changedView, visibility);
+        if (visibility == View.VISIBLE && changedView == this) {
+            updateUiElements();
+        }
+    }
+
+    @Override
+    public void onClick(View view) {
+        if (view == mConfigureImeShortcut) {
+            showConfigureInputMethods();
+            onFinishPanel(true);
+            return;
+        }
+    }
+
+    private void onFinishPanel(boolean closeKeyboard) {
+        setVisibility(View.GONE);
+        if (closeKeyboard) {
+            mImm.hideSoftInputFromWindow(getWindowToken(), 0);
+        }
+    }
+
+    private void startActivity(Intent intent) {
+        mContext.startActivity(intent);
+    }
+
+    private void showConfigureInputMethods() {
+        Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
+                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        startActivity(intent);
+    }
+
+    private View createInputMethodItem(
+            final InputMethodInfo imi, final InputMethodSubtype subtype) {
+        CharSequence subtypeName = getSubtypeName(imi, subtype);
+        CharSequence imiName = getIMIName(imi);
+        Drawable icon = getSubtypeIcon(imi, subtype);
+        View view = View.inflate(mContext, R.layout.status_bar_input_methods_item, null);
+        ImageView subtypeIcon = (ImageView)view.findViewById(R.id.item_icon);
+        TextView itemTitle = (TextView)view.findViewById(R.id.item_title);
+        TextView itemSubtitle = (TextView)view.findViewById(R.id.item_subtitle);
+        ImageView settingsIcon = (ImageView)view.findViewById(R.id.item_settings_icon);
+        View subtypeView = view.findViewById(R.id.item_subtype);
+        if (subtypeName == null) {
+            itemTitle.setText(imiName);
+            itemSubtitle.setVisibility(View.GONE);
+        } else {
+            itemTitle.setText(subtypeName);
+            itemSubtitle.setVisibility(View.VISIBLE);
+            itemSubtitle.setText(imiName);
+        }
+        subtypeIcon.setImageDrawable(icon);
+        final String settingsActivity = imi.getSettingsActivity();
+        if (!TextUtils.isEmpty(settingsActivity)) {
+            settingsIcon.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View arg0) {
+                    Intent intent = new Intent(Intent.ACTION_MAIN);
+                    intent.setClassName(imi.getPackageName(), settingsActivity);
+                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                            | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
+                            | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+                    startActivity(intent);
+                    onFinishPanel(true);
+                }
+            });
+        } else {
+            // Do not show the settings icon if the IME does not have a settings preference
+            view.findViewById(R.id.item_vertical_separator).setVisibility(View.GONE);
+            settingsIcon.setVisibility(View.GONE);
+        }
+        mRadioViewAndImiMap.put(
+                subtypeView, new Pair<InputMethodInfo, InputMethodSubtype> (imi, subtype));
+        subtypeView.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                Pair<InputMethodInfo, InputMethodSubtype> imiAndSubtype =
+                        updateRadioButtonsByView(view);
+                onFinishPanel(false);
+                setInputMethodAndSubtype(imiAndSubtype.first, imiAndSubtype.second);
+            }
+        });
+        return view;
+    }
+
+    private void updateUiElements() {
+        // TODO: Reuse subtype views.
+        mInputMethodMenuList.removeAllViews();
+        mRadioViewAndImiMap.clear();
+        HashMap<InputMethodInfo, List<InputMethodSubtype>> enabledIMIs
+                = getEnabledInputMethodAndSubtypeList();
+        // TODO: Sort by alphabet and mode.
+        Set<InputMethodInfo> cachedImiSet = enabledIMIs.keySet();
+        for (InputMethodInfo imi: cachedImiSet) {
+            List<InputMethodSubtype> subtypes = enabledIMIs.get(imi);
+            if (subtypes == null || subtypes.size() == 0) {
+                mInputMethodMenuList.addView(
+                        createInputMethodItem(imi, null));
+                continue;
+            }
+            for (InputMethodSubtype subtype: subtypes) {
+                mInputMethodMenuList.addView(createInputMethodItem(imi, subtype));
+            }
+        }
+        updateRadioButtons();
+    }
+
+    public void setIMEToken(IBinder token) {
+        mToken = token;
+    }
+
+    private void setInputMethodAndSubtype(InputMethodInfo imi, InputMethodSubtype subtype) {
+        if (mToken != null) {
+            mImm.setInputMethodAndSubtype(mToken, imi.getId(), subtype);
+        } else {
+            Log.w(TAG, "IME Token is not set yet.");
+        }
+    }
+
+    // Turn on the selected radio button when the user chooses the item
+    private Pair<InputMethodInfo, InputMethodSubtype> updateRadioButtonsByView(View selectedView) {
+        Pair<InputMethodInfo, InputMethodSubtype> selectedImiAndSubtype = null;
+        if (mRadioViewAndImiMap.containsKey(selectedView)) {
+            for (View radioView: mRadioViewAndImiMap.keySet()) {
+                RadioButton subtypeRadioButton =
+                        (RadioButton) radioView.findViewById(R.id.item_radio);
+                if (subtypeRadioButton == null) {
+                    Log.w(TAG, "RadioButton was not found in the selected subtype view");
+                    return null;
+                }
+                if (radioView == selectedView) {
+                    Pair<InputMethodInfo, InputMethodSubtype> imiAndSubtype =
+                        mRadioViewAndImiMap.get(radioView);
+                    selectedImiAndSubtype = imiAndSubtype;
+                    subtypeRadioButton.setChecked(true);
+                } else {
+                    subtypeRadioButton.setChecked(false);
+                }
+            }
+        }
+        return selectedImiAndSubtype;
+    }
+
+    private void updateRadioButtons() {
+        updateRadioButtonsByImiAndSubtype(
+                getCurrentInputMethodInfo(), mImm.getCurrentInputMethodSubtype());
+    }
+
+    // Turn on the selected radio button at startup
+    private void updateRadioButtonsByImiAndSubtype(
+            InputMethodInfo imi, InputMethodSubtype subtype) {
+        if (DEBUG) {
+            Log.d(TAG, "Update radio buttons by " + imi.getId() + ", " + subtype);
+        }
+        for (View radioView: mRadioViewAndImiMap.keySet()) {
+            RadioButton subtypeRadioButton =
+                    (RadioButton) radioView.findViewById(R.id.item_radio);
+            if (subtypeRadioButton == null) {
+                Log.w(TAG, "RadioButton was not found in the selected subtype view");
+                return;
+            }
+            Pair<InputMethodInfo, InputMethodSubtype> imiAndSubtype =
+                mRadioViewAndImiMap.get(radioView);
+            if (imiAndSubtype.first.getId().equals(imi.getId())
+                    && (imiAndSubtype.second == null || imiAndSubtype.second.equals(subtype))) {
+                subtypeRadioButton.setChecked(true);
+            } else {
+                subtypeRadioButton.setChecked(false);
+            }
+        }
+    }
+
+    private HashMap<InputMethodInfo, List<InputMethodSubtype>>
+            getEnabledInputMethodAndSubtypeList() {
+        String newEnabledIMIs = Settings.Secure.getString(
+                mContext.getContentResolver(), Settings.Secure.ENABLED_INPUT_METHODS);
+        if (mEnabledInputMethodAndSubtypesCacheStr == null
+                || !mEnabledInputMethodAndSubtypesCacheStr.equals(newEnabledIMIs)) {
+            mEnabledInputMethodAndSubtypesCache.clear();
+            final List<InputMethodInfo> imis = mImm.getEnabledInputMethodList();
+            for (InputMethodInfo imi: imis) {
+                mEnabledInputMethodAndSubtypesCache.put(imi,
+                        mImm.getEnabledInputMethodSubtypeList(imi, true));
+            }
+            mEnabledInputMethodAndSubtypesCacheStr = newEnabledIMIs;
+        }
+        return mEnabledInputMethodAndSubtypesCache;
+    }
+
+    private InputMethodInfo getCurrentInputMethodInfo() {
+        String curInputMethodId = Settings.Secure.getString(getContext()
+                .getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
+        Set<InputMethodInfo> cachedImiSet = mEnabledInputMethodAndSubtypesCache.keySet();
+        // 1. Search IMI in cache
+        for (InputMethodInfo imi: cachedImiSet) {
+            if (imi.getId().equals(curInputMethodId)) {
+                return imi;
+            }
+        }
+        // 2. Get current enabled IMEs and search IMI
+        cachedImiSet = getEnabledInputMethodAndSubtypeList().keySet();
+        for (InputMethodInfo imi: cachedImiSet) {
+            if (imi.getId().equals(curInputMethodId)) {
+                return imi;
+            }
+        }
+        return null;
+    }
+
+    private CharSequence getIMIName(InputMethodInfo imi) {
+        if (imi == null) return null;
+        return mPackageManager.getApplicationLabel(imi.getServiceInfo().applicationInfo);
+    }
+
+    private CharSequence getSubtypeName(InputMethodInfo imi, InputMethodSubtype subtype) {
+        if (imi == null || subtype == null) return null;
+        // TODO: Change the language of subtype name according to subtype's locale.
+        return mPackageManager.getText(
+                imi.getPackageName(), subtype.getNameResId(), imi.getServiceInfo().applicationInfo);
+    }
+
+    private Drawable getSubtypeIcon(InputMethodInfo imi, InputMethodSubtype subtype) {
+        if (imi != null) {
+            if (DEBUG) {
+                Log.d(TAG, "Update icons of IME: " + imi.getPackageName());
+                if (subtype != null) {
+                    Log.d(TAG, "subtype =" + subtype.getLocale() + "," + subtype.getMode());
+                }
+            }
+            if (subtype != null) {
+                return mPackageManager.getDrawable(imi.getPackageName(), subtype.getIconResId(),
+                        imi.getServiceInfo().applicationInfo);
+            } else if (imi.getSubtypes().size() > 0) {
+                return mPackageManager.getDrawable(imi.getPackageName(),
+                        imi.getSubtypes().get(0).getIconResId(),
+                        imi.getServiceInfo().applicationInfo);
+            } else {
+                try {
+                    return mPackageManager.getApplicationInfo(
+                            imi.getPackageName(), 0).loadIcon(mPackageManager);
+                } catch (PackageManager.NameNotFoundException e) {
+                    Log.w(TAG, "IME can't be found: " + imi.getPackageName());
+                }
+            }
+        }
+        return null;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index 020b955..af730fe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -80,6 +80,8 @@
     public static final String TAG = "TabletStatusBar";
 
     public static final int MAX_NOTIFICATION_ICONS = 5;
+    // IME switcher icon is big and occupy width of two icons
+    public static final int MAX_NOTIFICATION_ICONS_IME_BUTTON_VISIBLE = MAX_NOTIFICATION_ICONS - 2;
 
     public static final int MSG_OPEN_NOTIFICATION_PANEL = 1000;
     public static final int MSG_CLOSE_NOTIFICATION_PANEL = 1001;
@@ -89,6 +91,8 @@
     public static final int MSG_CLOSE_RECENTS_PANEL = 1021;
     public static final int MSG_SHOW_CHROME = 1030;
     public static final int MSG_HIDE_CHROME = 1031;
+    public static final int MSG_OPEN_INPUT_METHODS_PANEL = 1040;
+    public static final int MSG_CLOSE_INPUT_METHODS_PANEL = 1041;
 
     // Fitts' Law assistance for LatinIME; TODO: replace with a more general approach
     private static final boolean FAKE_SPACE_BAR = true;
@@ -155,6 +159,7 @@
 
     boolean mNotificationsOn = true;
     private RecentAppsPanel mRecentsPanel;
+    private InputMethodsPanel mInputMethodsPanel;
 
     public Context getContext() { return mContext; }
 
@@ -260,6 +265,28 @@
 
         WindowManagerImpl.getDefault().addView(mRecentsPanel, lp);
         mRecentsPanel.setBar(this);
+
+        // Input methods Panel
+        mInputMethodsPanel = (InputMethodsPanel) View.inflate(context,
+                R.layout.status_bar_input_methods_panel, null);
+        mInputMethodsPanel.setVisibility(View.GONE);
+        mInputMethodsPanel.setOnTouchListener(new TouchOutsideListener(
+                MSG_CLOSE_INPUT_METHODS_PANEL, mInputMethodsPanel));
+        mStatusBarView.setIgnoreChildren(3, mInputMethodSwitchButton, mInputMethodsPanel);
+        lp = new WindowManager.LayoutParams(
+                ViewGroup.LayoutParams.WRAP_CONTENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT,
+                WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL,
+                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                    | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
+                    | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
+                PixelFormat.TRANSLUCENT);
+        lp.gravity = Gravity.BOTTOM | Gravity.RIGHT;
+        lp.setTitle("InputMethodsPanel");
+        lp.windowAnimations = R.style.Animation_RecentPanel;
+
+        WindowManagerImpl.getDefault().addView(mInputMethodsPanel, lp);
     }
 
     @Override
@@ -351,6 +378,8 @@
         // The bar contents buttons
         mNotificationAndImeArea = (ViewGroup)sb.findViewById(R.id.notificationAndImeArea);
         mInputMethodSwitchButton = (InputMethodButton) sb.findViewById(R.id.imeSwitchButton);
+        // Overwrite the lister
+        mInputMethodSwitchButton.setOnClickListener(mOnClickListener);
 
         // for redirecting errant bar taps to the IME
         mFakeSpaceBar = sb.findViewById(R.id.fake_space_bar);
@@ -522,6 +551,14 @@
                         mRecentsPanel.show(false, true);
                     }
                     break;
+                case MSG_OPEN_INPUT_METHODS_PANEL:
+                    if (DEBUG) Slog.d(TAG, "opening input methods panel");
+                    if (mInputMethodsPanel != null) mInputMethodsPanel.setVisibility(View.VISIBLE);
+                    break;
+                case MSG_CLOSE_INPUT_METHODS_PANEL:
+                    if (DEBUG) Slog.d(TAG, "closing input methods panel");
+                    if (mInputMethodsPanel != null) mInputMethodsPanel.setVisibility(View.GONE);
+                    break;
                 case MSG_SHOW_CHROME:
                     if (DEBUG) Slog.d(TAG, "hiding shadows (lights on)");
                     mBarContents.setVisibility(View.VISIBLE);
@@ -774,6 +811,8 @@
         mHandler.sendEmptyMessage(MSG_CLOSE_NOTIFICATION_PANEL);
         mHandler.removeMessages(MSG_CLOSE_RECENTS_PANEL);
         mHandler.sendEmptyMessage(MSG_CLOSE_RECENTS_PANEL);
+        mHandler.removeMessages(MSG_CLOSE_INPUT_METHODS_PANEL);
+        mHandler.sendEmptyMessage(MSG_CLOSE_INPUT_METHODS_PANEL);
     }
 
     // called by StatusBar
@@ -803,7 +842,12 @@
         if (DEBUG) {
             Slog.d(TAG, (visible?"showing":"hiding") + " the IME button");
         }
+        int oldVisibility = mInputMethodSwitchButton.getVisibility();
         mInputMethodSwitchButton.setIMEButtonVisible(token, visible);
+        if (oldVisibility != mInputMethodSwitchButton.getVisibility()) {
+            updateNotificationIcons();
+        }
+        mInputMethodsPanel.setIMEToken(token);
         mBackButton.setImageResource(
                 visible ? R.drawable.ic_sysbar_back_ime : R.drawable.ic_sysbar_back);
         if (FAKE_SPACE_BAR) {
@@ -851,6 +895,8 @@
                 onClickNotificationTrigger();
             } else if (v == mRecentButton) {
                 onClickRecentButton();
+            } else if (v == mInputMethodSwitchButton) {
+                onClickInputMethodSwitchButton();
             }
         }
     };
@@ -890,6 +936,14 @@
         }
     }
 
+    public void onClickInputMethodSwitchButton() {
+        if (DEBUG) Slog.d(TAG, "clicked input methods panel; disabled=" + mDisabled);
+        int msg = (mInputMethodsPanel.getVisibility() == View.GONE) ?
+                MSG_OPEN_INPUT_METHODS_PANEL : MSG_CLOSE_INPUT_METHODS_PANEL;
+        mHandler.removeMessages(msg);
+        mHandler.sendEmptyMessage(msg);
+    }
+
     public NotificationClicker makeClicker(PendingIntent intent, String pkg, String tag, int id) {
         return new NotificationClicker(intent, pkg, tag, id);
     }
@@ -1086,7 +1140,12 @@
 
         ArrayList<View> toShow = new ArrayList<View>();
 
-        for (int i=0; i<MAX_NOTIFICATION_ICONS; i++) {
+        // When IME button is visible, the number of notification icons should be decremented
+        // to fit the upper limit.
+        final int maxNotificationIconsCount =
+                (mInputMethodSwitchButton.getVisibility() != View.GONE) ?
+                        MAX_NOTIFICATION_ICONS_IME_BUTTON_VISIBLE : MAX_NOTIFICATION_ICONS;
+        for (int i=0; i< maxNotificationIconsCount; i++) {
             if (i>=N) break;
             toShow.add(mNotns.get(N-i-1).icon);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java
index 6550765..4ee985d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBarView.java
@@ -27,9 +27,9 @@
 public class TabletStatusBarView extends FrameLayout {
     private Handler mHandler;
 
-    private View[] mIgnoreChildren = new View[3];
-    private View[] mPanels = new View[3];
-    private int[] mPos = new int[2];
+    private final View[] mIgnoreChildren = new View[4];
+    private final View[] mPanels = new View[4];
+    private final int[] mPos = new int[2];
 
     public TabletStatusBarView(Context context) {
         super(context);
@@ -39,6 +39,7 @@
         super(context, attrs);
     }
 
+    @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         if (ev.getAction() == MotionEvent.ACTION_DOWN) {
             if (TabletStatusBar.DEBUG) {
@@ -48,12 +49,16 @@
             mHandler.sendEmptyMessage(TabletStatusBar.MSG_CLOSE_NOTIFICATION_PANEL);
             mHandler.removeMessages(TabletStatusBar.MSG_CLOSE_RECENTS_PANEL);
             mHandler.sendEmptyMessage(TabletStatusBar.MSG_CLOSE_RECENTS_PANEL);
+            mHandler.removeMessages(TabletStatusBar.MSG_CLOSE_INPUT_METHODS_PANEL);
+            mHandler.sendEmptyMessage(TabletStatusBar.MSG_CLOSE_INPUT_METHODS_PANEL);
 
             for (int i=0; i < mPanels.length; i++) {
                 if (mPanels[i] != null && mPanels[i].getVisibility() == View.VISIBLE) {
                     if (eventInside(mIgnoreChildren[i], ev)) {
                         if (TabletStatusBar.DEBUG) {
-                            Slog.d(TabletStatusBar.TAG, "TabletStatusBarView eating event for view: " + mIgnoreChildren[i]);
+                            Slog.d(TabletStatusBar.TAG,
+                                    "TabletStatusBarView eating event for view: "
+                                    + mIgnoreChildren[i]);
                         }
                         return true;
                     }
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index 1f06dcc..5e33f05 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -221,8 +221,7 @@
         final AlertDialog.Builder ab = new AlertDialog.Builder(mContext);
 
         ab.setAdapter(mAdapter, this)
-                .setInverseBackgroundForced(true)
-                .setTitle(R.string.global_actions);
+                .setInverseBackgroundForced(true);
 
         final AlertDialog dialog = ab.create();
         dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
@@ -249,6 +248,7 @@
         } else {
             mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
         }
+        mDialog.setTitle(R.string.global_actions);
     }
 
 
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 243fa07..a6037aa 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -122,8 +122,10 @@
 import android.media.AudioManager;
 
 import java.io.File;
+import java.io.FileDescriptor;
 import java.io.FileReader;
 import java.io.IOException;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 
 /**
@@ -2808,4 +2810,70 @@
         // disable key repeat when screen is off
         return mScreenOn;
     }
+
+    public void dump(String prefix, FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.print(prefix); pw.print("mSafeMode="); pw.print(mSafeMode);
+                pw.print(" mSystemRead="); pw.println(mSystemReady);
+        pw.print(prefix); pw.print("mLidOpen="); pw.print(mLidOpen);
+                pw.print(" mLidOpenRotation="); pw.print(mLidOpenRotation);
+                pw.print(" mHdmiPlugged="); pw.println(mHdmiPlugged);
+        pw.print(prefix); pw.print("mUiMode="); pw.print(mUiMode);
+                pw.print(" mDockMode="); pw.print(mDockMode);
+                pw.print(" mCarDockRotation="); pw.print(mCarDockRotation);
+                pw.print(" mDeskDockRotation="); pw.println(mDeskDockRotation);
+        pw.print(prefix); pw.print("mUserRotationMode="); pw.print(mUserRotationMode);
+                pw.print(" mUserRotation="); pw.print(mUserRotation);
+                pw.print("mAllowAllRotations="); pw.println(mAllowAllRotations);
+        pw.print(prefix); pw.print("mAccelerometerDefault="); pw.print(mAccelerometerDefault);
+                pw.print(" mCurrentAppOrientation="); pw.println(mCurrentAppOrientation);
+        pw.print(prefix); pw.print("mCarDockEnablesAccelerometer=");
+                pw.print(mCarDockEnablesAccelerometer);
+                pw.print(" mDeskDockEnablesAccelerometer=");
+                pw.println(mDeskDockEnablesAccelerometer);
+        pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
+                pw.print(mLidKeyboardAccessibility);
+                pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
+                pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
+        pw.print(prefix); pw.print("mScreenOn="); pw.print(mScreenOn);
+                pw.print(" mOrientationSensorEnabled="); pw.print(mOrientationSensorEnabled);
+                pw.print(" mHasSoftInput="); pw.println(mHasSoftInput);
+        pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft);
+                pw.print(","); pw.print(mUnrestrictedScreenTop);
+                pw.print(") "); pw.print(mUnrestrictedScreenWidth);
+                pw.print("x"); pw.println(mUnrestrictedScreenHeight);
+        pw.print(prefix); pw.print("mRestrictedScreen=("); pw.print(mRestrictedScreenLeft);
+                pw.print(","); pw.print(mRestrictedScreenTop);
+                pw.print(") "); pw.print(mRestrictedScreenWidth);
+                pw.print("x"); pw.println(mRestrictedScreenHeight);
+        pw.print(prefix); pw.print("mCur=("); pw.print(mCurLeft);
+                pw.print(","); pw.print(mCurTop);
+                pw.print(")-("); pw.print(mCurRight);
+                pw.print(","); pw.print(mCurBottom); pw.println(")");
+        pw.print(prefix); pw.print("mContent=("); pw.print(mContentLeft);
+                pw.print(","); pw.print(mContentTop);
+                pw.print(")-("); pw.print(mContentRight);
+                pw.print(","); pw.print(mContentBottom); pw.println(")");
+        pw.print(prefix); pw.print("mDock=("); pw.print(mDockLeft);
+                pw.print(","); pw.print(mDockTop);
+                pw.print(")-("); pw.print(mDockRight);
+                pw.print(","); pw.print(mDockBottom); pw.println(")");
+        pw.print(prefix); pw.print("mDockLayer="); pw.println(mDockLayer);
+        pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
+                pw.println(mTopFullscreenOpaqueWindowState);
+        pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
+                pw.print(" mForceStatusBar="); pw.print(mForceStatusBar);
+                pw.print(" mHideLockScreen="); pw.println(mHideLockScreen);
+        pw.print(prefix); pw.print("mDismissKeyguard="); pw.print(mDismissKeyguard);
+                pw.print(" mHomePressed="); pw.println(mHomePressed);
+        pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
+                pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
+                pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
+        pw.print(prefix); pw.print("mEndcallBehavior="); pw.print(mEndcallBehavior);
+                pw.print(" mIncallPowerBehavior="); pw.print(mIncallPowerBehavior);
+                pw.print(" mLongPressOnHomeBehavior="); pw.println(mLongPressOnHomeBehavior);
+        pw.print(prefix); pw.print("mLandscapeRotation="); pw.print(mLandscapeRotation);
+                pw.print(" mSeascapeRotation="); pw.println(mSeascapeRotation);
+        pw.print(prefix); pw.print("mPortraitRotation="); pw.print(mPortraitRotation);
+                pw.print(" mUpsideDownRotation="); pw.println(mUpsideDownRotation);
+    }
 }
diff --git a/services/java/com/android/server/InputManager.java b/services/java/com/android/server/InputManager.java
index 5c2048b..6dca523 100644
--- a/services/java/com/android/server/InputManager.java
+++ b/services/java/com/android/server/InputManager.java
@@ -542,7 +542,7 @@
         @SuppressWarnings("unused")
         public PointerIcon getPointerIcon() {
             return PointerIcon.load(mContext.getResources(),
-                    com.android.internal.R.drawable.pointericon_default);
+                    com.android.internal.R.drawable.pointer_arrow_icon);
         }
     }
 }
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index a2684fb..2b98795 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -427,6 +427,7 @@
                             // Uh oh, current input method is no longer around!
                             // Pick another one...
                             Slog.i(TAG, "Current input method removed: " + curInputMethodId);
+                            mStatusBar.setIMEButtonVisible(mCurToken, false);
                             if (!chooseNewDefaultIMELocked()) {
                                 changed = true;
                                 curIm = null;
@@ -489,7 +490,8 @@
         statusBar.setIconVisibility("ime", false);
 
         // mSettings should be created before buildInputMethodListLocked
-        mSettings = new InputMethodSettings(context.getContentResolver(), mMethodMap, mMethodList);
+        mSettings = new InputMethodSettings(
+                mRes, context.getContentResolver(), mMethodMap, mMethodList);
         buildInputMethodListLocked(mMethodList, mMethodMap);
         mSettings.enableAllIMEsIfThereIsNoEnabledIME();
 
@@ -574,7 +576,7 @@
             if (!allowsImplicitlySelectedSubtypes || enabledSubtypes.size() > 0) {
                 return enabledSubtypes;
             } else {
-                return getApplicableSubtypesLocked(imi.getSubtypes());
+                return getApplicableSubtypesLocked(mRes, imi.getSubtypes());
             }
         }
     }
@@ -1020,9 +1022,11 @@
             }
             if (subtype != mCurrentSubtype) {
                 synchronized (mMethodMap) {
+                    if (subtype != null) {
+                        setSelectedInputMethodAndSubtypeLocked(info, subtypeId, true);
+                    }
                     if (mCurMethod != null) {
                         try {
-                            setSelectedInputMethodAndSubtypeLocked(info, subtypeId, true);
                             if (mInputShown) {
                                 // If mInputShown is false, there is no IME button on the
                                 // system bar.
@@ -1677,7 +1681,7 @@
                 ArrayList<String> subtypes = immis.get(i).second;
                 if (subtypes != null && subtypes.size() == 0) {
                     ArrayList<InputMethodSubtype> applicableSubtypes =
-                            getApplicableSubtypesLocked(imi.getSubtypes());
+                            getApplicableSubtypesLocked(mRes, imi.getSubtypes());
                     final int numSubtypes = applicableSubtypes.size();
                     for (int j = 0; j < numSubtypes; ++j) {
                         subtypes.add(String.valueOf(applicableSubtypes.get(j).hashCode()));
@@ -1797,19 +1801,14 @@
                     });
 
             if (showSubtypes) {
-                mDialogBuilder.setPositiveButton(com.android.internal.R.string.more_item_label,
+                mDialogBuilder.setPositiveButton(
+                        com.android.internal.R.string.configure_input_methods,
                         new DialogInterface.OnClickListener() {
                             public void onClick(DialogInterface dialog, int whichButton) {
                                 showConfigureInputMethods();
                             }
                         });
             }
-            mDialogBuilder.setNegativeButton(com.android.internal.R.string.cancel,
-                    new DialogInterface.OnClickListener() {
-                        public void onClick(DialogInterface dialog, int whichButton) {
-                            hideInputMethodMenu();
-                        }
-                    });
             mSwitchingDialog = mDialogBuilder.create();
             mSwitchingDialog.getWindow().setType(
                     WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG);
@@ -1979,9 +1978,9 @@
         return NOT_A_SUBTYPE_ID;
     }
 
-    private ArrayList<InputMethodSubtype> getApplicableSubtypesLocked(
-            List<InputMethodSubtype> subtypes) {
-        final String systemLocale = mRes.getConfiguration().locale.toString();
+    private static ArrayList<InputMethodSubtype> getApplicableSubtypesLocked(
+            Resources res, List<InputMethodSubtype> subtypes) {
+        final String systemLocale = res.getConfiguration().locale.toString();
         if (TextUtils.isEmpty(systemLocale)) return new ArrayList<InputMethodSubtype>();
         HashMap<String, InputMethodSubtype> applicableModeAndSubtypesMap =
                 new HashMap<String, InputMethodSubtype>();
@@ -2015,7 +2014,7 @@
                 applicableModeAndSubtypesMap.values());
         if (!containsKeyboardSubtype) {
             InputMethodSubtype lastResortKeyboardSubtype = findLastResortApplicableSubtypeLocked(
-                    subtypes, SUBTYPE_MODE_KEYBOARD, systemLocale, true);
+                    res, subtypes, SUBTYPE_MODE_KEYBOARD, systemLocale, true);
             if (lastResortKeyboardSubtype != null) {
                 applicableSubtypes.add(lastResortKeyboardSubtype);
             }
@@ -2033,14 +2032,14 @@
      * it will return the first subtype matched with mode
      * @return the most applicable subtypeId
      */
-    private InputMethodSubtype findLastResortApplicableSubtypeLocked(
-            List<InputMethodSubtype> subtypes, String mode, String locale,
+    private static InputMethodSubtype findLastResortApplicableSubtypeLocked(
+            Resources res, List<InputMethodSubtype> subtypes, String mode, String locale,
             boolean canIgnoreLocaleAsLastResort) {
         if (subtypes == null || subtypes.size() == 0) {
             return null;
         }
         if (TextUtils.isEmpty(locale)) {
-            locale = mRes.getConfiguration().locale.toString();
+            locale = res.getConfiguration().locale.toString();
         }
         final String language = locale.substring(0, 2);
         boolean partialMatchFound = false;
@@ -2097,29 +2096,29 @@
                 continue;
             }
             InputMethodSubtype subtype = null;
-            final List<InputMethodSubtype> explicitlyEnabledSubtypes =
-                    mSettings.getEnabledInputMethodSubtypeListLocked(imi);
-            // 1. Search by the current subtype's locale from explicitlyEnabledSubtypes.
+            final List<InputMethodSubtype> enabledSubtypes =
+                    getEnabledInputMethodSubtypeList(imi, true);
+            // 1. Search by the current subtype's locale from enabledSubtypes.
             if (mCurrentSubtype != null) {
                 subtype = findLastResortApplicableSubtypeLocked(
-                        explicitlyEnabledSubtypes, mode, mCurrentSubtype.getLocale(), false);
+                        mRes, enabledSubtypes, mode, mCurrentSubtype.getLocale(), false);
             }
-            // 2. Search by the system locale from explicitlyEnabledSubtypes.
-            // 3. Search the first enabled subtype matched with mode from explicitlyEnabledSubtypes.
+            // 2. Search by the system locale from enabledSubtypes.
+            // 3. Search the first enabled subtype matched with mode from enabledSubtypes.
             if (subtype == null) {
                 subtype = findLastResortApplicableSubtypeLocked(
-                        explicitlyEnabledSubtypes, mode, null, true);
+                        mRes, enabledSubtypes, mode, null, true);
             }
             // 4. Search by the current subtype's locale from all subtypes.
             if (subtype == null && mCurrentSubtype != null) {
                 subtype = findLastResortApplicableSubtypeLocked(
-                        imi.getSubtypes(), mode, mCurrentSubtype.getLocale(), false);
+                        mRes, imi.getSubtypes(), mode, mCurrentSubtype.getLocale(), false);
             }
             // 5. Search by the system locale from all subtypes.
             // 6. Search the first enabled subtype matched with mode from all subtypes.
             if (subtype == null) {
                 subtype = findLastResortApplicableSubtypeLocked(
-                        imi.getSubtypes(), mode, null, true);
+                        mRes, imi.getSubtypes(), mode, null, true);
             }
             if (subtype != null) {
                 if (imiId.equals(mCurMethodId)) {
@@ -2179,8 +2178,8 @@
                         // the most applicable subtype from all subtypes whose mode is
                         // SUBTYPE_MODE_KEYBOARD. This is an exceptional case, so we will hardcode
                         // the mode.
-                        mCurrentSubtype = findLastResortApplicableSubtypeLocked(imi.getSubtypes(),
-                                SUBTYPE_MODE_KEYBOARD, null, true);
+                        mCurrentSubtype = findLastResortApplicableSubtypeLocked(
+                                mRes, imi.getSubtypes(), SUBTYPE_MODE_KEYBOARD, null, true);
                     }
                 } else {
                     mCurrentSubtype =
@@ -2258,6 +2257,7 @@
         private final TextUtils.SimpleStringSplitter mSubtypeSplitter =
                 new TextUtils.SimpleStringSplitter(INPUT_METHOD_SUBTYPE_SEPARATER);
 
+        private final Resources mRes;
         private final ContentResolver mResolver;
         private final HashMap<String, InputMethodInfo> mMethodMap;
         private final ArrayList<InputMethodInfo> mMethodList;
@@ -2277,8 +2277,9 @@
         }
 
         public InputMethodSettings(
-                ContentResolver resolver, HashMap<String, InputMethodInfo> methodMap,
-                ArrayList<InputMethodInfo> methodList) {
+                Resources res, ContentResolver resolver,
+                HashMap<String, InputMethodInfo> methodMap, ArrayList<InputMethodInfo> methodList) {
+            mRes = res;
             mResolver = resolver;
             mMethodMap = methodMap;
             mMethodList = methodList;
@@ -2518,8 +2519,9 @@
                 // If imeId is empty, returns the first IME and subtype in the history
                 if (TextUtils.isEmpty(imeId) || imeInTheHistory.equals(imeId)) {
                     final String subtypeInTheHistory = imeAndSubtype.second;
-                    final String subtypeHashCode = getEnabledSubtypeForInputMethodAndSubtypeLocked(
-                            enabledImes, imeInTheHistory, subtypeInTheHistory);
+                    final String subtypeHashCode =
+                            getEnabledSubtypeHashCodeForInputMethodAndSubtypeLocked(
+                                    enabledImes, imeInTheHistory, subtypeInTheHistory);
                     if (!TextUtils.isEmpty(subtypeHashCode)) {
                         if (DEBUG) {
                             Slog.d(TAG, "Enabled subtype found in the history:" + subtypeHashCode);
@@ -2534,14 +2536,36 @@
             return null;
         }
 
-        private String getEnabledSubtypeForInputMethodAndSubtypeLocked(List<Pair<String,
+        private String getEnabledSubtypeHashCodeForInputMethodAndSubtypeLocked(List<Pair<String,
                 ArrayList<String>>> enabledImes, String imeId, String subtypeHashCode) {
             for (Pair<String, ArrayList<String>> enabledIme: enabledImes) {
                 if (enabledIme.first.equals(imeId)) {
-                    for (String s: enabledIme.second) {
-                        if (s.equals(subtypeHashCode)) {
-                            // If both imeId and subtypeId are enabled, return subtypeId.
-                            return s;
+                    final ArrayList<String> enabledSubtypes = enabledIme.second;
+                    if (enabledSubtypes.size() == 0) {
+                        // If there are no enabled subtypes, applicable subtypes are enabled
+                        // implicitly.
+                        InputMethodInfo ime = mMethodMap.get(imeId);
+                        // If IME is enabled and no subtypes are enabled, applicable subtypes
+                        // are enabled implicitly, so needs to treat them to be enabled.
+                        if (ime != null && ime.getSubtypes().size() > 0) {
+                            List<InputMethodSubtype> implicitlySelectedSubtypes =
+                                getApplicableSubtypesLocked(mRes, ime.getSubtypes());
+                            if (implicitlySelectedSubtypes != null) {
+                                final int N = implicitlySelectedSubtypes.size();
+                                for (int i = 0; i < N; ++i) {
+                                    final InputMethodSubtype st = implicitlySelectedSubtypes.get(i);
+                                    if (String.valueOf(st.hashCode()).equals(subtypeHashCode)) {
+                                        return subtypeHashCode;
+                                    }
+                                }
+                            }
+                        }
+                    } else {
+                        for (String s: enabledSubtypes) {
+                            if (s.equals(subtypeHashCode)) {
+                                // If both imeId and subtypeId are enabled, return subtypeId.
+                                return s;
+                            }
                         }
                     }
                     // If imeId was enabled but subtypeId was disabled.
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index b196f74..1efc645 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -4646,16 +4646,52 @@
         }
     }
 
-    public void setPackageObbPath(String packageName, String path) {
+    public void setPackageObbPaths(String packageName, String[] paths) {
         if (DEBUG_OBB)
-            Log.v(TAG, "Setting .obb path for " + packageName + " to: " + path);
-        PackageSetting pkgSetting;
+            Log.v(TAG, "Setting .obb paths for " + packageName + " to: " + Arrays.toString(paths));
+        final int uid = Binder.getCallingUid();
+        final int permission = mContext.checkCallingPermission(
+                android.Manifest.permission.INSTALL_PACKAGES);
+        final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
+        if (!allowedByPermission) {
+            throw new SecurityException("Permission denial: attempt to set .obb file from pid="
+                    + Binder.getCallingPid());
+        }
+        synchronized (mPackages) {
+            final PackageSetting pkgSetting = mSettings.mPackages.get(packageName);
+            if (pkgSetting == null) {
+                throw new IllegalArgumentException("Unknown package: " + packageName);
+            }
+
+            if (paths != null) {
+                if (paths.length == 0) {
+                    // Don't bother storing an empty array.
+                    paths = null;
+                } else {
+                    // Don't allow the caller to manipulate our copy of the
+                    // list.
+                    paths = paths.clone();
+                }
+            }
+
+            // Only write settings file if the new and old settings are not the
+            // same.
+            if (!Arrays.equals(paths, pkgSetting.obbPathStrings)) {
+                pkgSetting.obbPathStrings = paths;
+                mSettings.writeLP();
+            }
+        }
+    }
+
+    public String[] getPackageObbPaths(String packageName) {
+        if (DEBUG_OBB)
+            Log.v(TAG, "Getting .obb paths for " + packageName);
         final int uid = Binder.getCallingUid();
         final int permission = mContext.checkCallingPermission(
                 android.Manifest.permission.INSTALL_PACKAGES);
         final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED);
         synchronized (mPackages) {
-            pkgSetting = mSettings.mPackages.get(packageName);
+            final PackageSetting pkgSetting = mSettings.mPackages.get(packageName);
             if (pkgSetting == null) {
                 throw new IllegalArgumentException("Unknown package: " + packageName);
             }
@@ -4664,8 +4700,7 @@
                         + Binder.getCallingPid() + ", uid=" + uid + ", package uid="
                         + pkgSetting.userId);
             }
-            pkgSetting.obbPathString = path;
-            mSettings.writeLP();
+            return pkgSetting.obbPathStrings;
         }
     }
 
@@ -7238,7 +7273,7 @@
                     pw.print("    codePath="); pw.println(ps.codePathString);
                     pw.print("    resourcePath="); pw.println(ps.resourcePathString);
                     pw.print("    nativeLibraryPath="); pw.println(ps.nativeLibraryPathString);
-                    pw.print("    obbPath="); pw.println(ps.obbPathString);
+                    pw.print("    obbPaths="); pw.println(Arrays.toString(ps.obbPathStrings));
                     pw.print("    versionCode="); pw.println(ps.versionCode);
                     if (ps.pkg != null) {
                         pw.print("    versionName="); pw.println(ps.pkg.mVersionName);
@@ -7453,6 +7488,12 @@
     static class PackageSignatures {
         private Signature[] mSignatures;
 
+        PackageSignatures(PackageSignatures orig) {
+            if (orig != null && orig.mSignatures != null) {
+                mSignatures = orig.mSignatures.clone();
+            }
+        }
+
         PackageSignatures(Signature[] sigs) {
             assignSignatures(sigs);
         }
@@ -7788,6 +7829,15 @@
             setFlags(pkgFlags);
         }
 
+        GrantedPermissions(GrantedPermissions base) {
+            pkgFlags = base.pkgFlags;
+            grantedPermissions = (HashSet<String>) base.grantedPermissions.clone();
+
+            if (base.gids != null) {
+                gids = base.gids.clone();
+            }
+        }
+
         void setFlags(int pkgFlags) {
             this.pkgFlags = pkgFlags & (
                     ApplicationInfo.FLAG_SYSTEM |
@@ -7808,14 +7858,14 @@
         File resourcePath;
         String resourcePathString;
         String nativeLibraryPathString;
-        String obbPathString;
+        String[] obbPathStrings;
         long timeStamp;
         long firstInstallTime;
         long lastUpdateTime;
         int versionCode;
 
         boolean uidError;
-        
+
         PackageSignatures signatures = new PackageSignatures();
 
         boolean permissionsFixed;
@@ -7841,6 +7891,48 @@
             init(codePath, resourcePath, nativeLibraryPathString, pVersionCode);
         }
 
+        /**
+         * New instance of PackageSetting with one-level-deep cloning.
+         */
+        PackageSettingBase(PackageSettingBase base) {
+            super(base);
+
+            name = base.name;
+            realName = base.realName;
+            codePath = base.codePath;
+            codePathString = base.codePathString;
+            resourcePath = base.resourcePath;
+            resourcePathString = base.resourcePathString;
+            nativeLibraryPathString = base.nativeLibraryPathString;
+
+            if (base.obbPathStrings != null) {
+                obbPathStrings = base.obbPathStrings.clone();
+            }
+
+            timeStamp = base.timeStamp;
+            firstInstallTime = base.firstInstallTime;
+            lastUpdateTime = base.lastUpdateTime;
+            versionCode = base.versionCode;
+
+            uidError = base.uidError;
+
+            signatures = new PackageSignatures(base.signatures);
+
+            permissionsFixed = base.permissionsFixed;
+            haveGids = base.haveGids;
+
+            disabledComponents = (HashSet<String>) base.disabledComponents.clone();
+
+            enabledComponents = (HashSet<String>) base.enabledComponents.clone();
+
+            enabled = base.enabled;
+            installStatus = base.installStatus;
+
+            origPackage = base.origPackage;
+
+            installerPackageName = base.installerPackageName;
+        }
+
         void init(File codePath, File resourcePath, String nativeLibraryPathString,
                 int pVersionCode) {
             this.codePath = codePath;
@@ -7871,6 +7963,9 @@
             timeStamp = newStamp;
         }
 
+        /**
+         * Make a shallow copy of this package settings.
+         */
         public void copyFrom(PackageSettingBase base) {
             grantedPermissions = base.grantedPermissions;
             gids = base.gids;
@@ -7930,18 +8025,16 @@
                     pkgFlags);
         }
 
+        /**
+         * New instance of PackageSetting replicating the original settings.
+         * Note that it keeps the same PackageParser.Package instance.
+         */
         PackageSetting(PackageSetting orig) {
-            super(orig.name, orig.realName, orig.codePath, orig.resourcePath,
-                    orig.nativeLibraryPathString, orig.versionCode, orig.pkgFlags);
-            copyFrom(orig);
-        }
+            super(orig);
 
-        public void copyFrom(PackageSetting base) {
-            super.copyFrom((PackageSettingBase) base);
-
-            userId = base.userId;
-            sharedUser = base.sharedUser;
-            pkg = base.pkg;
+            userId = orig.userId;
+            pkg = orig.pkg;
+            sharedUser = orig.sharedUser;
         }
 
         @Override
@@ -8173,7 +8266,7 @@
                 // a little trick...  when we install the new package, we don't
                 // want to modify the existing PackageSetting for the built-in
                 // version.  so at this point we need a new PackageSetting that
-                // is okay to much with.
+                // is okay to muck with.
                 PackageSetting newp = new PackageSetting(p);
                 replacePackageLP(name, newp);
                 return true;
@@ -8874,8 +8967,15 @@
             if (pkg.installerPackageName != null) {
                 serializer.attribute(null, "installer", pkg.installerPackageName);
             }
-            if (pkg.obbPathString != null) {
-                serializer.attribute(null, "obbPath", pkg.obbPathString);
+            if (pkg.obbPathStrings != null && pkg.obbPathStrings.length > 0) {
+                int N = pkg.obbPathStrings.length;
+                serializer.startTag(null, "obbs");
+                for (int i = 0; i < N; i++) {
+                    serializer.startTag(null, "obb");
+                    serializer.attribute(null, "path", pkg.obbPathStrings[i]);
+                    serializer.endTag(null, "obb");
+                }
+                serializer.endTag(null, "obbs");
             }
             pkg.signatures.writeXml(serializer, "sigs", mPastSignatures);
             if ((pkg.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
@@ -9279,7 +9379,6 @@
             String codePathStr = null;
             String resourcePathStr = null;
             String nativeLibraryPathStr = null;
-            String obbPathStr = null;
             String systemStr = null;
             String installerPackageName = null;
             String uidError = null;
@@ -9299,7 +9398,6 @@
                 codePathStr = parser.getAttributeValue(null, "codePath");
                 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
                 nativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath");
-                obbPathStr = parser.getAttributeValue(null, "obbPath");
                 version = parser.getAttributeValue(null, "version");
                 if (version != null) {
                     try {
@@ -9424,7 +9522,6 @@
                 packageSetting.uidError = "true".equals(uidError);
                 packageSetting.installerPackageName = installerPackageName;
                 packageSetting.nativeLibraryPathString = nativeLibraryPathStr;
-                packageSetting.obbPathString = obbPathStr;
                 final String enabledStr = parser.getAttributeValue(null, "enabled");
                 if (enabledStr != null) {
                     if (enabledStr.equalsIgnoreCase("true")) {
@@ -9472,6 +9569,8 @@
                         readGrantedPermissionsLP(parser,
                                 packageSetting.grantedPermissions);
                         packageSetting.permissionsFixed = true;
+                    } else if (tagName.equals("obbs")) {
+                        readObbPathsLP(packageSetting, parser);
                     } else {
                         reportSettingsProblem(Log.WARN,
                                 "Unknown element under <package>: "
@@ -9676,6 +9775,34 @@
             }
         }
 
+        private void readObbPathsLP(PackageSettingBase packageSetting, XmlPullParser parser)
+                throws XmlPullParserException, IOException {
+            final List<String> obbPaths = new ArrayList<String>();
+            final int outerDepth = parser.getDepth();
+            int type;
+            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                    continue;
+                }
+
+                final String tagName = parser.getName();
+                if (tagName.equals("obb")) {
+                    final String path = parser.getAttributeValue(null, "path");
+                    obbPaths.add(path);
+                } else {
+                    reportSettingsProblem(Log.WARN, "Unknown element under <obbs>: "
+                            + parser.getName());
+                }
+                XmlUtils.skipCurrentTag(parser);
+            }
+            if (obbPaths.size() == 0) {
+                return;
+            } else {
+                packageSetting.obbPathStrings = obbPaths.toArray(new String[obbPaths.size()]);
+            }
+        }
+
         // Returns -1 if we could not find an available UserId to assign
         private int newUserIdLP(Object obj) {
             // Let's be stupidly inefficient for now...
diff --git a/services/java/com/android/server/ScreenRotationAnimation.java b/services/java/com/android/server/ScreenRotationAnimation.java
index 19cc203..2ad9cbe 100644
--- a/services/java/com/android/server/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/ScreenRotationAnimation.java
@@ -60,7 +60,8 @@
     final Matrix mSnapshotFinalMatrix = new Matrix();
     final float[] mTmpFloats = new float[9];
 
-    public ScreenRotationAnimation(Context context, Display display, SurfaceSession session) {
+    public ScreenRotationAnimation(Context context, Display display, SurfaceSession session,
+            boolean inTransaction) {
         mContext = context;
         mDisplay = display;
 
@@ -84,60 +85,70 @@
         mOriginalWidth = mDisplayMetrics.widthPixels;
         mOriginalHeight = mDisplayMetrics.heightPixels;
 
-        Surface.openTransaction();
+        if (!inTransaction) {
+            if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG,
+                    ">>> OPEN TRANSACTION ScreenRotationAnimation");
+            Surface.openTransaction();
+        }
         
         try {
-            mSurface = new Surface(session, 0, "FreezeSurface",
-                    -1, mWidth, mHeight, PixelFormat.OPAQUE, 0);
-            mSurface.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER * 200);
-        } catch (Surface.OutOfResourcesException e) {
-            Slog.w(TAG, "Unable to allocate freeze surface", e);
-        }
-        
-        if (false) {
             try {
-                int size = mOriginalWidth > mOriginalHeight ? mOriginalWidth : mOriginalHeight;
-                mBlackSurface = new Surface(session, 0, "BlackSurface",
-                        -1, size, size, PixelFormat.OPAQUE, Surface.FX_SURFACE_DIM);
-                mBlackSurface.setAlpha(1.0f);
-                mBlackSurface.setLayer(0);
+                mSurface = new Surface(session, 0, "FreezeSurface",
+                        -1, mWidth, mHeight, PixelFormat.OPAQUE, 0);
+                mSurface.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER * 200);
             } catch (Surface.OutOfResourcesException e) {
-                Slog.w(TAG, "Unable to allocate black surface", e);
+                Slog.w(TAG, "Unable to allocate freeze surface", e);
             }
-        }
-        
-        setRotation(display.getRotation());
 
-        if (mSurface != null) {
-            Rect dirty = new Rect(0, 0, mWidth, mHeight);
-            Canvas c = null;
-            try {
-                c = mSurface.lockCanvas(dirty);
-            } catch (IllegalArgumentException e) {
-                Slog.w(TAG, "Unable to lock surface", e);
-                return;
-            } catch (Surface.OutOfResourcesException e) {
-                Slog.w(TAG, "Unable to lock surface", e);
-                return;
+            if (false) {
+                try {
+                    int size = mOriginalWidth > mOriginalHeight ? mOriginalWidth : mOriginalHeight;
+                    mBlackSurface = new Surface(session, 0, "BlackSurface",
+                            -1, size, size, PixelFormat.OPAQUE, Surface.FX_SURFACE_DIM);
+                    mBlackSurface.setAlpha(1.0f);
+                    mBlackSurface.setLayer(0);
+                } catch (Surface.OutOfResourcesException e) {
+                    Slog.w(TAG, "Unable to allocate black surface", e);
+                }
             }
-            if (c == null) {
-                Slog.w(TAG, "Null surface");
-                return;
+
+            setRotation(display.getRotation());
+
+            if (mSurface != null) {
+                Rect dirty = new Rect(0, 0, mWidth, mHeight);
+                Canvas c = null;
+                try {
+                    c = mSurface.lockCanvas(dirty);
+                } catch (IllegalArgumentException e) {
+                    Slog.w(TAG, "Unable to lock surface", e);
+                    return;
+                } catch (Surface.OutOfResourcesException e) {
+                    Slog.w(TAG, "Unable to lock surface", e);
+                    return;
+                }
+                if (c == null) {
+                    Slog.w(TAG, "Null surface");
+                    return;
+                }
+        
+                if (screenshot != null) {
+                    c.drawBitmap(screenshot, 0, 0, new Paint(0));
+                } else {
+                    c.drawColor(Color.GREEN);
+                }
+
+                mSurface.unlockCanvasAndPost(c);
+            }
+        } finally {
+            if (!inTransaction) {
+                Surface.closeTransaction();
+                if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG,
+                        "<<< CLOSE TRANSACTION ScreenRotationAnimation");
             }
     
             if (screenshot != null) {
-                c.drawBitmap(screenshot, 0, 0, new Paint(0));
-            } else {
-                c.drawColor(Color.GREEN);
+                screenshot.recycle();
             }
-    
-            mSurface.unlockCanvasAndPost(c);
-        }
-        
-        Surface.closeTransaction();
-
-        if (screenshot != null) {
-            screenshot.recycle();
         }
     }
 
diff --git a/services/java/com/android/server/Watchdog.java b/services/java/com/android/server/Watchdog.java
index 1b885f5..2a25c2a 100644
--- a/services/java/com/android/server/Watchdog.java
+++ b/services/java/com/android/server/Watchdog.java
@@ -425,7 +425,7 @@
             // First collect stack traces from all threads of the system process.
             // Then kill this process so that the system will restart.
 
-            String name = (mCurrentMonitor != null) ?
+            final String name = (mCurrentMonitor != null) ?
                     mCurrentMonitor.getClass().getName() : "null";
             EventLog.writeEvent(EventLogTags.WATCHDOG, name);
 
@@ -434,7 +434,8 @@
             if (mPhonePid > 0) pids.add(mPhonePid);
             // Pass !waitedHalf so that just in case we somehow wind up here without having
             // dumped the halfway stacks, we properly re-initialize the trace file.
-            File stack = ActivityManagerService.dumpStackTraces(!waitedHalf, pids, null, null);
+            final File stack = ActivityManagerService.dumpStackTraces(
+                    !waitedHalf, pids, null, null);
 
             // Give some extra time to make sure the stack traces get written.
             // The system's been hanging for a minute, another second or two won't hurt much.
@@ -445,7 +446,19 @@
                 dumpKernelStackTraces();
             }
 
-            mActivity.addErrorToDropBox("watchdog", null, null, null, name, null, stack, null);
+            // Try to add the error to the dropbox, but assuming that the ActivityManager
+            // itself may be deadlocked.  (which has happened, causing this statement to
+            // deadlock and the watchdog as a whole to be ineffective)
+            Thread dropboxThread = new Thread("watchdogWriteToDropbox") {
+                    public void run() {
+                        mActivity.addErrorToDropBox(
+                                "watchdog", null, null, null, name, null, stack, null);
+                    }
+                };
+            dropboxThread.start();
+            try {
+                dropboxThread.join(2000);  // wait up to 2 seconds for it to return.
+            } catch (InterruptedException ignored) {}
 
             // Only kill the process if the debugger is not attached.
             if (!Debug.isDebuggerConnected()) {
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index e9bf624..8d9cb31 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -149,6 +149,7 @@
         implements Watchdog.Monitor {
     static final String TAG = "WindowManager";
     static final boolean DEBUG = false;
+    static final boolean DEBUG_ADD_REMOVE = false;
     static final boolean DEBUG_FOCUS = false;
     static final boolean DEBUG_ANIM = false;
     static final boolean DEBUG_LAYOUT = false;
@@ -158,6 +159,7 @@
     static final boolean DEBUG_INPUT_METHOD = false;
     static final boolean DEBUG_VISIBILITY = false;
     static final boolean DEBUG_WINDOW_MOVEMENT = false;
+    static final boolean DEBUG_TOKEN_MOVEMENT = false;
     static final boolean DEBUG_ORIENTATION = false;
     static final boolean DEBUG_CONFIGURATION = false;
     static final boolean DEBUG_APP_TRANSITIONS = false;
@@ -296,12 +298,6 @@
             new HashMap<IBinder, WindowToken>();
 
     /**
-     * The same tokens as mTokenMap, stored in a list for efficient iteration
-     * over them.
-     */
-    final ArrayList<WindowToken> mTokenList = new ArrayList<WindowToken>();
-
-    /**
      * Window tokens that are in the process of exiting, but still
      * on screen for animations.
      */
@@ -310,7 +306,7 @@
     /**
      * Z-ordered (bottom-most first) list of all application tokens, for
      * controlling the ordering of windows in different applications.  This
-     * contains WindowToken objects.
+     * contains AppWindowToken objects.
      */
     final ArrayList<AppWindowToken> mAppTokens = new ArrayList<AppWindowToken>();
 
@@ -344,6 +340,11 @@
     final ArrayList<WindowState> mPendingRemove = new ArrayList<WindowState>();
 
     /**
+     * Used when processing mPendingRemove to avoid working on the original array.
+     */
+    WindowState[] mPendingRemoveTmp = new WindowState[20];
+
+    /**
      * Windows whose surface should be destroyed.
      */
     final ArrayList<WindowState> mDestroySurface = new ArrayList<WindowState>();
@@ -360,6 +361,12 @@
      */
     ArrayList<WindowState> mForceRemoves;
 
+    /**
+     * Used when rebuilding window list to keep track of windows that have
+     * been removed.
+     */
+    WindowState[] mRebuildTmp = new WindowState[20];
+
     IInputMethodManager mInputMethodManager;
 
     SurfaceSession mFxSession;
@@ -685,7 +692,7 @@
             // deferred rotation
             if (performRotation) {
                 if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-drag rotation");
-                boolean changed = setRotationUncheckedLocked(rotation, animFlags);
+                boolean changed = setRotationUncheckedLocked(rotation, animFlags, false);
                 if (changed) {
                     sendNewConfiguration();
                 }
@@ -696,9 +703,14 @@
             final int myPid = Process.myPid();
 
             // Move the surface to the given touch
+            if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION notifyMoveLw");
             mSurface.openTransaction();
-            mSurface.setPosition((int)(x - mThumbOffsetX), (int)(y - mThumbOffsetY));
-            mSurface.closeTransaction();
+            try {
+                mSurface.setPosition((int)(x - mThumbOffsetX), (int)(y - mThumbOffsetY));
+            } finally {
+                mSurface.closeTransaction();
+                if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION notifyMoveLw");
+            }
 
             // Tell the affected window
             WindowState touchedWin = getTouchedWinAtPointLw(x, y);
@@ -1089,7 +1101,7 @@
 
     private void placeWindowAfter(WindowState pos, WindowState window) {
         final int i = mWindows.indexOf(pos);
-        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
+        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
             TAG, "Adding window " + window + " at "
             + (i+1) + " of " + mWindows.size() + " (after " + pos + ")");
         mWindows.add(i+1, window);
@@ -1098,7 +1110,7 @@
 
     private void placeWindowBefore(WindowState pos, WindowState window) {
         final int i = mWindows.indexOf(pos);
-        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
+        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
             TAG, "Adding window " + window + " at "
             + i + " of " + mWindows.size() + " (before " + pos + ")");
         mWindows.add(i, window);
@@ -1156,9 +1168,10 @@
                                 //apptoken note that the window could be a floating window
                                 //that was created later or a window at the top of the list of
                                 //windows associated with this token.
-                                if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
-                                        TAG, "Adding window " + win + " at "
-                                        + (newIdx+1) + " of " + N);
+                                if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) {
+                                    Slog.v(TAG, "Adding window " + win + " at "
+                                            + (newIdx+1) + " of " + N);
+                                }
                                 localmWindows.add(newIdx+1, win);
                                 mWindowsChanged = true;
                             }
@@ -1237,9 +1250,10 @@
                                     break;
                                 }
                             }
-                            if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
-                                    TAG, "Adding window " + win + " at "
-                                    + i + " of " + N);
+                            if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) {
+                                Slog.v(TAG, "Adding window " + win + " at "
+                                        + i + " of " + N);
+                            }
                             localmWindows.add(i, win);
                             mWindowsChanged = true;
                         }
@@ -1255,13 +1269,14 @@
                     }
                 }
                 if (i < 0) i = 0;
-                if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT) Slog.v(
+                if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
                         TAG, "Adding window " + win + " at "
                         + i + " of " + N);
                 localmWindows.add(i, win);
                 mWindowsChanged = true;
             }
             if (addToToken) {
+                if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
                 token.windows.add(tokenWindowsPos, win);
             }
 
@@ -1284,6 +1299,7 @@
                     // in the same sublayer.
                     if (wSublayer >= sublayer) {
                         if (addToToken) {
+                            if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
                             token.windows.add(i, win);
                         }
                         placeWindowBefore(
@@ -1295,6 +1311,7 @@
                     // in the same sublayer.
                     if (wSublayer > sublayer) {
                         if (addToToken) {
+                            if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
                             token.windows.add(i, win);
                         }
                         placeWindowBefore(w, win);
@@ -1304,6 +1321,7 @@
             }
             if (i >= NA) {
                 if (addToToken) {
+                    if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + win + " to " + token);
                     token.windows.add(win);
                 }
                 if (sublayer < 0) {
@@ -1478,7 +1496,7 @@
         int pos = findDesiredInputMethodWindowIndexLocked(true);
         if (pos >= 0) {
             win.mTargetAppToken = mInputMethodTarget.mAppToken;
-            if (DEBUG_WINDOW_MOVEMENT) Slog.v(
+            if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(
                     TAG, "Adding input method window " + win + " at " + pos);
             mWindows.add(pos, win);
             mWindowsChanged = true;
@@ -2028,9 +2046,10 @@
                 }
 
                 // Now stick it in.
-                if (DEBUG_WALLPAPER || DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
-                        "Moving wallpaper " + wallpaper
-                        + " from " + oldIndex + " to " + foundI);
+                if (DEBUG_WALLPAPER || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) {
+                    Slog.v(TAG, "Moving wallpaper " + wallpaper
+                            + " from " + oldIndex + " to " + foundI);
+                }
 
                 localmWindows.add(foundI, wallpaper);
                 mWindowsChanged = true;
@@ -2349,7 +2368,6 @@
 
             if (addToken) {
                 mTokenMap.put(attrs.token, token);
-                mTokenList.add(token);
             }
             win.attach();
             mWindowMap.put(client.asBinder(), win);
@@ -2417,7 +2435,7 @@
                 TAG, "New client " + client.asBinder()
                 + ": window=" + win);
             
-            if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked()) {
+            if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) {
                 reportNewConfig = true;
             }
         }
@@ -2504,7 +2522,7 @@
         // So just update orientation if needed.
         if (wasVisible && computeForcedAppOrientationLocked()
                 != mForcedAppOrientation
-                && updateOrientationFromAppTokensLocked()) {
+                && updateOrientationFromAppTokensLocked(false)) {
             mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
         }
         updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
@@ -2512,6 +2530,18 @@
     }
 
     private void removeWindowInnerLocked(Session session, WindowState win) {
+        if (win.mRemoved) {
+            // Nothing to do.
+            return;
+        }
+
+        for (int i=win.mChildWindows.size()-1; i>=0; i--) {
+            WindowState cwin = win.mChildWindows.get(i);
+            Slog.w(TAG, "Force-removing child win " + cwin + " from container "
+                    + win);
+            removeWindowInnerLocked(cwin.mSession, cwin);
+        }
+
         win.mRemoved = true;
 
         if (mInputMethodTarget == win) {
@@ -2527,8 +2557,10 @@
         mPolicy.removeWindowLw(win);
         win.removeLocked();
 
+        if (DEBUG_ADD_REMOVE) Slog.v(TAG, "removeWindowInnerLocked: " + win);
         mWindowMap.remove(win.mClient.asBinder());
         mWindows.remove(win);
+        mPendingRemove.remove(win);
         mWindowsChanged = true;
         if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Final remove of window: " + win);
 
@@ -2540,6 +2572,7 @@
 
         final WindowToken token = win.mToken;
         final AppWindowToken atoken = win.mAppToken;
+        if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + win + " from " + token);
         token.windows.remove(win);
         if (atoken != null) {
             atoken.allAppWindows.remove(win);
@@ -2550,7 +2583,6 @@
         if (token.windows.size() == 0) {
             if (!token.explicit) {
                 mTokenMap.remove(token.token);
-                mTokenList.remove(token);
             } else if (atoken != null) {
                 atoken.firstWindowDrawn = false;
             }
@@ -2610,15 +2642,17 @@
             synchronized (mWindowMap) {
                 WindowState w = windowForClientLocked(session, client, false);
                 if ((w != null) && (w.mSurface != null)) {
-                    if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION");
+                    if (SHOW_TRANSACTIONS) Slog.i(TAG,
+                            ">>> OPEN TRANSACTION setTransparentRegion");
                     Surface.openTransaction();
                     try {
                         if (SHOW_TRANSACTIONS) logSurface(w,
                                 "transparentRegionHint=" + region, null);
                         w.mSurface.setTransparentRegionHint(region);
                     } finally {
-                        if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION");
                         Surface.closeTransaction();
+                        if (SHOW_TRANSACTIONS) Slog.i(TAG,
+                                "<<< CLOSE TRANSACTION setTransparentRegion");
                     }
                 }
             }
@@ -2956,7 +2990,7 @@
             if (assignLayers) {
                 assignLayersLocked();
             }
-            configChanged = updateOrientationFromAppTokensLocked();
+            configChanged = updateOrientationFromAppTokensLocked(false);
             performLayoutAndPlaceSurfacesLocked();
             if (displayed && win.mIsWallpaper) {
                 updateWallpaperOffsetLocked(win, mDisplay.getWidth(),
@@ -3313,7 +3347,6 @@
             }
             wtoken = new WindowToken(token, type, true);
             mTokenMap.put(token, wtoken);
-            mTokenList.add(wtoken);
             if (type == TYPE_WALLPAPER) {
                 mWallpaperTokens.add(wtoken);
             }
@@ -3329,7 +3362,6 @@
         final long origId = Binder.clearCallingIdentity();
         synchronized(mWindowMap) {
             WindowToken wtoken = mTokenMap.remove(token);
-            mTokenList.remove(wtoken);
             if (wtoken != null) {
                 boolean delayed = false;
                 if (!wtoken.hidden) {
@@ -3405,10 +3437,9 @@
             wtoken.groupId = groupId;
             wtoken.appFullscreen = fullscreen;
             wtoken.requestedOrientation = requestedOrientation;
+            if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + wtoken);
             mAppTokens.add(addPos, wtoken);
-            if (localLOGV) Slog.v(TAG, "Adding new app token: " + wtoken);
             mTokenMap.put(token.asBinder(), wtoken);
-            mTokenList.add(wtoken);
 
             // Application tokens start out hidden.
             wtoken.hidden = true;
@@ -3525,7 +3556,7 @@
         long ident = Binder.clearCallingIdentity();
         
         synchronized(mWindowMap) {
-            if (updateOrientationFromAppTokensLocked()) {
+            if (updateOrientationFromAppTokensLocked(false)) {
                 if (freezeThisOneIfNeeded != null) {
                     AppWindowToken wtoken = findAppWindowToken(
                             freezeThisOneIfNeeded);
@@ -3547,7 +3578,7 @@
                     if (currentConfig.diff(mTempConfiguration) != 0) {
                         mWaitingForConfig = true;
                         mLayoutNeeded = true;
-                        startFreezingDisplayLocked();
+                        startFreezingDisplayLocked(false);
                         config = new Configuration(mTempConfiguration);
                     }
                 }
@@ -3572,8 +3603,8 @@
      * @see android.view.IWindowManager#updateOrientationFromAppTokens(
      * android.os.IBinder)
      */
-    boolean updateOrientationFromAppTokensLocked() {
-        if (mDisplayFrozen) {
+    boolean updateOrientationFromAppTokensLocked(boolean inTransaction) {
+        if (mDisplayFrozen || mOpeningApps.size() > 0 || mClosingApps.size() > 0) {
             // If the display is frozen, some activities may be in the middle
             // of restarting, and thus have removed their old window.  If the
             // window has the flag to hide the lock screen, then the lock screen
@@ -3593,7 +3624,8 @@
                 //action like disabling/enabling sensors etc.,
                 mPolicy.setCurrentOrientationLw(req);
                 if (setRotationUncheckedLocked(WindowManagerPolicy.USE_LAST_ROTATION,
-                        mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE)) {
+                        mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE,
+                        inTransaction)) {
                     changed = true;
                 }
             }
@@ -3819,10 +3851,12 @@
                         startingWindow.mToken = wtoken;
                         startingWindow.mRootToken = wtoken;
                         startingWindow.mAppToken = wtoken;
-                        if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
+                        if (DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG,
                                 "Removing starting window: " + startingWindow);
                         mWindows.remove(startingWindow);
                         mWindowsChanged = true;
+                        if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing starting " + startingWindow
+                                + " from " + ttoken);
                         ttoken.windows.remove(startingWindow);
                         ttoken.allAppWindows.remove(startingWindow);
                         addWindowToListInOrderLocked(startingWindow, true);
@@ -4168,7 +4202,7 @@
                 wtoken.freezingScreen = true;
                 mAppsFreezingScreen++;
                 if (mAppsFreezingScreen == 1) {
-                    startFreezingDisplayLocked();
+                    startFreezingDisplayLocked(false);
                     mH.removeMessages(H.APP_FREEZE_TIMEOUT);
                     mH.sendMessageDelayed(mH.obtainMessage(H.APP_FREEZE_TIMEOUT),
                             5000);
@@ -4237,7 +4271,6 @@
         final long origId = Binder.clearCallingIdentity();
         synchronized(mWindowMap) {
             WindowToken basewtoken = mTokenMap.remove(token);
-            mTokenList.remove(basewtoken);
             if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) {
                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken);
                 delayed = setTokenVisibilityLocked(wtoken, null, false, WindowManagerPolicy.TRANSIT_UNSET, true);
@@ -4257,6 +4290,8 @@
                         + " animating=" + wtoken.animating);
                 if (delayed) {
                     // set the token aside because it has an active animation to be finished
+                    if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
+                            "removeAppToken make exiting: " + wtoken);
                     mExitingAppTokens.add(wtoken);
                 } else {
                     // Make sure there is no animation running on this token,
@@ -4265,6 +4300,8 @@
                     wtoken.animation = null;
                     wtoken.animating = false;
                 }
+                if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
+                        "removeAppToken: " + wtoken);
                 mAppTokens.remove(wtoken);
                 wtoken.removed = true;
                 if (wtoken.startingData != null) {
@@ -4391,18 +4428,21 @@
             if (!added && cwin.mSubLayer >= 0) {
                 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding child window at "
                         + index + ": " + cwin);
+                win.mRebuilding = false;
                 mWindows.add(index, win);
                 index++;
                 added = true;
             }
             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
                     + index + ": " + cwin);
+            cwin.mRebuilding = false;
             mWindows.add(index, cwin);
             index++;
         }
         if (!added) {
             if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG, "Re-adding window at "
                     + index + ": " + win);
+            win.mRebuilding = false;
             mWindows.add(index, win);
             index++;
         }
@@ -4428,6 +4468,9 @@
             if (DEBUG_REORDER) Slog.v(TAG, "Initial app tokens:");
             if (DEBUG_REORDER) dumpAppTokensLocked();
             final AppWindowToken wtoken = findAppWindowToken(token);
+            if (DEBUG_TOKEN_MOVEMENT || DEBUG_REORDER) Slog.v(TAG,
+                    "Start moving token " + wtoken + " initially at "
+                    + mAppTokens.indexOf(wtoken));
             if (wtoken == null || !mAppTokens.remove(wtoken)) {
                 Slog.w(TAG, "Attempting to reorder token that doesn't exist: "
                       + token + " (" + wtoken + ")");
@@ -4435,6 +4478,7 @@
             }
             mAppTokens.add(index, wtoken);
             if (DEBUG_REORDER) Slog.v(TAG, "Moved " + token + " to " + index + ":");
+            else if (DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "Moved " + token + " to " + index);
             if (DEBUG_REORDER) dumpAppTokensLocked();
 
             final long origId = Binder.clearCallingIdentity();
@@ -4462,6 +4506,8 @@
         for (int i=0; i<N; i++) {
             IBinder token = tokens.get(i);
             final AppWindowToken wtoken = findAppWindowToken(token);
+            if (DEBUG_REORDER || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
+                    "Temporarily removing " + wtoken + " from " + mAppTokens.indexOf(wtoken));
             if (!mAppTokens.remove(wtoken)) {
                 Slog.w(TAG, "Attempting to reorder token that doesn't exist: "
                       + token + " (" + wtoken + ")");
@@ -4535,6 +4581,8 @@
             for (int i=0; i<N; i++) {
                 AppWindowToken wt = findAppWindowToken(tokens.get(i));
                 if (wt != null) {
+                    if (DEBUG_TOKEN_MOVEMENT || DEBUG_REORDER) Slog.v(TAG,
+                            "Adding next to top: " + wt);
                     mAppTokens.add(wt);
                     if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
                         mToTopApps.remove(wt);
@@ -4567,6 +4615,8 @@
             for (int i=0; i<N; i++) {
                 AppWindowToken wt = findAppWindowToken(tokens.get(i));
                 if (wt != null) {
+                    if (DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
+                            "Adding next to bottom: " + wt + " at " + pos);
                     mAppTokens.add(pos, wt);
                     if (mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
                         mToTopApps.remove(wt);
@@ -4934,12 +4984,17 @@
                 }
             }
 
+            if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION showStrictModeViolation");
             Surface.openTransaction();
-            if (mStrictModeFlash == null) {
-                mStrictModeFlash = new StrictModeFlash(mDisplay, mFxSession);
+            try {
+                if (mStrictModeFlash == null) {
+                    mStrictModeFlash = new StrictModeFlash(mDisplay, mFxSession);
+                }
+                mStrictModeFlash.setVisibility(on);
+            } finally {
+                Surface.closeTransaction();
+                if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION showStrictModeViolation");
             }
-            mStrictModeFlash.setVisibility(on);
-            Surface.closeTransaction();
         }
     }
 
@@ -5084,7 +5139,7 @@
         long origId = Binder.clearCallingIdentity();
         boolean changed;
         synchronized(mWindowMap) {
-            changed = setRotationUncheckedLocked(rotation, animFlags);
+            changed = setRotationUncheckedLocked(rotation, animFlags, false);
         }
 
         if (changed || alwaysSendConfiguration) {
@@ -5102,7 +5157,7 @@
      * Returns null if the rotation has been changed.  In this case YOU
      * MUST CALL setNewConfiguration() TO UNFREEZE THE SCREEN.
      */
-    public boolean setRotationUncheckedLocked(int rotation, int animFlags) {
+    public boolean setRotationUncheckedLocked(int rotation, int animFlags, boolean inTransaction) {
         if (mDragState != null) {
             // Potential rotation during a drag.  Don't do the rotation now, but make
             // a note to perform the rotation later.
@@ -5137,17 +5192,28 @@
                     2000);
             mWaitingForConfig = true;
             mLayoutNeeded = true;
-            startFreezingDisplayLocked();
+            startFreezingDisplayLocked(inTransaction);
             Slog.i(TAG, "Setting rotation to " + rotation + ", animFlags=" + animFlags);
             mInputManager.setDisplayOrientation(0, rotation);
             if (mDisplayEnabled) {
                 if (CUSTOM_SCREEN_ROTATION) {
                     Surface.freezeDisplay(0);
-                    Surface.openTransaction();
-                    if (mScreenRotationAnimation != null) {
-                        mScreenRotationAnimation.setRotation(rotation);
+                    if (!inTransaction) {
+                        if (SHOW_TRANSACTIONS) Slog.i(TAG,
+                                ">>> OPEN TRANSACTION setRotationUnchecked");
+                        Surface.openTransaction();
                     }
-                    Surface.closeTransaction();
+                    try {
+                        if (mScreenRotationAnimation != null) {
+                            mScreenRotationAnimation.setRotation(rotation);
+                        }
+                    } finally {
+                        if (!inTransaction) {
+                            Surface.closeTransaction();
+                            if (SHOW_TRANSACTIONS) Slog.i(TAG,
+                                    "<<< CLOSE TRANSACTION setRotationUnchecked");
+                        }
+                    }
                     Surface.setOrientation(0, rotation, animFlags);
                     Surface.unfreezeDisplay(0);
                 } else {
@@ -5566,7 +5632,13 @@
 
     public Configuration computeNewConfiguration() {
         synchronized (mWindowMap) {
-            return computeNewConfigurationLocked();
+            Configuration config = computeNewConfigurationLocked();
+            if (config == null && mWaitingForConfig) {
+                // Nothing changed but we are waiting for something... stop that!
+                mWaitingForConfig = false;
+                performLayoutAndPlaceSurfacesLocked();
+            }
+            return config;
         }
     }
 
@@ -5952,7 +6024,7 @@
          * ordinary dispatch. */
         public boolean interceptKeyBeforeDispatching(
                 InputWindowHandle focus, KeyEvent event, int policyFlags) {
-            WindowState windowState = (WindowState) focus.windowState;
+            WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
             return mPolicy.interceptKeyBeforeDispatching(windowState, event, policyFlags);
         }
         
@@ -5960,7 +6032,7 @@
          * the application did not handle. */
         public KeyEvent dispatchUnhandledKey(
                 InputWindowHandle focus, KeyEvent event, int policyFlags) {
-            WindowState windowState = (WindowState) focus.windowState;
+            WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
             return mPolicy.dispatchUnhandledKey(windowState, event, policyFlags);
         }
         
@@ -6509,6 +6581,7 @@
 
                 // Make the surface visible at the proper location
                 final Surface surface = mDragState.mSurface;
+                if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION performDrag");
                 Surface.openTransaction();
                 try {
                     surface.setPosition((int)(touchX - thumbCenterX),
@@ -6518,6 +6591,7 @@
                     surface.show();
                 } finally {
                     Surface.closeTransaction();
+                    if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION performDrag");
                 }
             }
 
@@ -6840,6 +6914,10 @@
         // Is this window now (or just being) removed?
         boolean mRemoved;
 
+        // Temp for keeping track of windows that have been removed when
+        // rebuilding window list.
+        boolean mRebuilding;
+
         // For debugging, this is the last information given to the surface flinger.
         boolean mSurfaceShown;
         int mSurfaceX, mSurfaceY, mSurfaceW, mSurfaceH;
@@ -6892,6 +6970,7 @@
                         + TYPE_LAYER_OFFSET;
                 mSubLayer = mPolicy.subWindowTypeToLayerLw(a.type);
                 mAttachedWindow = attachedWindow;
+                if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + this + " to " + mAttachedWindow);
                 mAttachedWindow.mChildWindows.add(this);
                 mLayoutAttached = mAttrs.type !=
                         WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
@@ -7197,9 +7276,8 @@
                     + ", set left=" + mFrame.left + " top=" + mFrame.top
                     + ", animLayer=" + mAnimLayer);
                 if (SHOW_TRANSACTIONS) {
-                    Slog.i(TAG, ">>> OPEN TRANSACTION");
-                    if (SHOW_TRANSACTIONS) logSurface(this,
-                            "CREATE pos=(" + mFrame.left + "," + mFrame.top + ") (" +
+                    Slog.i(TAG, ">>> OPEN TRANSACTION createSurfaceLocked");
+                    logSurface(this, "CREATE pos=(" + mFrame.left + "," + mFrame.top + ") (" +
                             mFrame.width() + "x" + mFrame.height() + "), layer=" +
                             mAnimLayer + " HIDE", null);
                 }
@@ -7224,8 +7302,8 @@
                     }
                     mLastHidden = true;
                 } finally {
-                    if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION");
                     Surface.closeTransaction();
+                    if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION createSurfaceLocked");
                 }
                 if (localLOGV) Slog.v(
                         TAG, "Created surface " + this);
@@ -7897,6 +7975,7 @@
             disposeInputChannel();
             
             if (mAttachedWindow != null) {
+                if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + this + " from " + mAttachedWindow);
                 mAttachedWindow.mChildWindows.remove(this);
             }
             destroySurfaceLocked();
@@ -9146,12 +9225,18 @@
         int lastWallpaper = -1;
         int numRemoved = 0;
 
+        if (mRebuildTmp.length < NW) {
+            mRebuildTmp = new WindowState[NW+10];
+        }
+
         // First remove all existing app windows.
         i=0;
         while (i < NW) {
             WindowState w = mWindows.get(i);
             if (w.mAppToken != null) {
                 WindowState win = mWindows.remove(i);
+                win.mRebuilding = true;
+                mRebuildTmp[numRemoved] = win;
                 mWindowsChanged = true;
                 if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG,
                         "Rebuild removing window: " + win);
@@ -9189,6 +9274,21 @@
         if (i != numRemoved) {
             Slog.w(TAG, "Rebuild removed " + numRemoved
                     + " windows but added " + i);
+            for (i=0; i<numRemoved; i++) {
+                WindowState ws = mRebuildTmp[i];
+                if (ws.mRebuilding) {
+                    StringWriter sw = new StringWriter();
+                    PrintWriter pw = new PrintWriter(sw);
+                    ws.dump(pw, "");
+                    pw.flush();
+                    Slog.w(TAG, "This window was lost: " + ws);
+                    Slog.w(TAG, sw.toString());
+                }
+            }
+            Slog.w(TAG, "Current app token list:");
+            dumpAppTokensLocked();
+            Slog.w(TAG, "Final window list:");
+            dumpWindowsLocked();
         }
     }
 
@@ -9261,7 +9361,7 @@
         try {
             if (mForceRemoves != null) {
                 recoveringMemory = true;
-                // Wait a little it for things to settle down, and off we go.
+                // Wait a little bit for things to settle down, and off we go.
                 for (int i=0; i<mForceRemoves.size(); i++) {
                     WindowState ws = mForceRemoves.get(i);
                     Slog.i(TAG, "Force removing: " + ws);
@@ -9284,14 +9384,17 @@
         try {
             performLayoutAndPlaceSurfacesLockedInner(recoveringMemory);
 
-            int i = mPendingRemove.size()-1;
-            if (i >= 0) {
-                while (i >= 0) {
-                    WindowState w = mPendingRemove.get(i);
-                    removeWindowInnerLocked(w.mSession, w);
-                    i--;
+            int N = mPendingRemove.size();
+            if (N > 0) {
+                if (mPendingRemoveTmp.length < N) {
+                    mPendingRemoveTmp = new WindowState[N+10];
                 }
+                mPendingRemove.toArray(mPendingRemoveTmp);
                 mPendingRemove.clear();
+                for (int i=0; i<N; i++) {
+                    WindowState w = mPendingRemoveTmp[i];
+                    removeWindowInnerLocked(w.mSession, w);
+                }
 
                 mInLayout = false;
                 assignLayersLocked();
@@ -9469,7 +9572,7 @@
             createWatermark = true;
         }
 
-        if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION");
+        if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
 
         Surface.openTransaction();
 
@@ -9507,7 +9610,7 @@
                     }
                     if ((changes&WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG) != 0) {
                         if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
-                        if (updateOrientationFromAppTokensLocked()) {
+                        if (updateOrientationFromAppTokensLocked(true)) {
                             mLayoutNeeded = true;
                             mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
                         }
@@ -9735,12 +9838,9 @@
                 if (tokenMayBeDrawn) {
                     // See if any windows have been drawn, so they (and others
                     // associated with them) can now be shown.
-                    final int NT = mTokenList.size();
+                    final int NT = mAppTokens.size();
                     for (i=0; i<NT; i++) {
-                        AppWindowToken wtoken = mTokenList.get(i).appWindowToken;
-                        if (wtoken == null) {
-                            continue;
-                        }
+                        AppWindowToken wtoken = mAppTokens.get(i);
                         if (wtoken.freezingScreen) {
                             int numInteresting = wtoken.numInterestingWindows;
                             if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
@@ -9966,7 +10066,8 @@
 
                         // This has changed the visibility of windows, so perform
                         // a new layout to get them all up-to-date.
-                        changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
+                        changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT
+                                | WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
                         mLayoutNeeded = true;
                         if (!moveInputMethodWindowsIfNeededLocked(true)) {
                             assignLayersLocked();
@@ -10192,7 +10293,7 @@
                                 // as running out of memory), don't take down the
                                 // entire system.
                                 Slog.e(TAG, "Failure updating surface of " + w
-                                        + "size=(" + width + "x" + height
+                                        + " size=(" + width + "x" + height
                                         + "), pos=(" + w.mShownFrame.left
                                         + "," + w.mShownFrame.top + ")", e);
                                 if (!recoveringMemory) {
@@ -10543,8 +10644,6 @@
                 }
                 mBlurShown = false;
             }
-
-            if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION");
         } catch (RuntimeException e) {
             Slog.e(TAG, "Unhandled exception in Window Manager", e);
         }
@@ -10553,6 +10652,8 @@
         
         Surface.closeTransaction();
 
+        if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
+
         if (mWatermark != null) {
             mWatermark.drawIfNeeded();
         }
@@ -10642,6 +10743,8 @@
                 // soon as their animations are complete
                 token.animation = null;
                 token.animating = false;
+                if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
+                        "performLayout: App token exiting now removed" + token);
                 mAppTokens.remove(token);
                 mExitingAppTokens.remove(i);
             }
@@ -10753,7 +10856,7 @@
             }
             return true;
         } catch (RuntimeException e) {
-            Slog.w(TAG, "Failure showing surface " + win.mSurface + " in " + win);
+            Slog.w(TAG, "Failure showing surface " + win.mSurface + " in " + win, e);
         }
 
         reclaimSomeSurfaceMemoryLocked(win, "show");
@@ -10788,6 +10891,7 @@
                                 + " token=" + win.mToken
                                 + " pid=" + ws.mSession.mPid
                                 + " uid=" + ws.mSession.mUid);
+                        if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
                         ws.mSurface.destroy();
                         ws.mSurfaceShown = false;
                         ws.mSurface = null;
@@ -10795,10 +10899,11 @@
                         i--;
                         N--;
                         leakedSurface = true;
-                    } else if (win.mAppToken != null && win.mAppToken.clientHidden) {
+                    } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
                         Slog.w(TAG, "LEAKED SURFACE (app token hidden): "
                                 + ws + " surface=" + ws.mSurface
                                 + " token=" + win.mAppToken);
+                        if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", null);
                         ws.mSurface.destroy();
                         ws.mSurfaceShown = false;
                         ws.mSurface = null;
@@ -10836,6 +10941,7 @@
                 // surface and ask the app to request another one.
                 Slog.w(TAG, "Looks like we have reclaimed some memory, clearing surface for retry.");
                 if (surface != null) {
+                    if (SHOW_TRANSACTIONS) logSurface(win, "RECOVER DESTROY", null);
                     surface.destroy();
                     win.mSurfaceShown = false;
                     win.mSurface = null;
@@ -10963,7 +11069,7 @@
         return result;
     }
 
-    private void startFreezingDisplayLocked() {
+    private void startFreezingDisplayLocked(boolean inTransaction) {
         if (mDisplayFrozen) {
             return;
         }
@@ -11005,7 +11111,7 @@
             }
             if (mScreenRotationAnimation == null) {
                 mScreenRotationAnimation = new ScreenRotationAnimation(mContext,
-                        mDisplay, mFxSession);
+                        mDisplay, mFxSession, inTransaction);
             }
         } else {
             Surface.freezeDisplay(0);
@@ -11046,7 +11152,7 @@
         // to avoid inconsistent states.  However, something interesting
         // could have actually changed during that time so re-evaluate it
         // now to catch that.
-        if (updateOrientationFromAppTokensLocked()) {
+        if (updateOrientationFromAppTokensLocked(false)) {
             mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
         }
 
@@ -11351,14 +11457,6 @@
                     token.dump(pw, "    ");
                 }
             }
-            if (mTokenList.size() > 0) {
-                pw.println(" ");
-                pw.println("  Window token list:");
-                for (int i=0; i<mTokenList.size(); i++) {
-                    pw.print("  #"); pw.print(i); pw.print(": ");
-                            pw.println(mTokenList.get(i));
-                }
-            }
             if (mWallpaperTokens.size() > 0) {
                 pw.println(" ");
                 pw.println("  Wallpaper tokens:");
@@ -11482,6 +11580,8 @@
             } else {
                 pw.println("  NO DISPLAY");
             }
+            pw.println("  Policy:");
+            mPolicy.dump("    ", fd, pw, args);
         }
     }
 
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 761dcd1..17ef88d 100755
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -2612,6 +2612,7 @@
                     if (localLOGV) Slog.v(
                         TAG, "Removing this entry!  frozen=" + r.haveState
                         + " finishing=" + r.finishing);
+                    r.makeFinishing();
                     mMainStack.mHistory.remove(i);
 
                     r.inHistory = false;
@@ -6607,7 +6608,7 @@
                     if (r.state == ActivityState.RESUMED
                             || r.state == ActivityState.PAUSING
                             || r.state == ActivityState.PAUSED) {
-                        if (!r.isHomeActivity) {
+                        if (!r.isHomeActivity || mHomeProcess != r.app) {
                             Slog.w(TAG, "  Force finishing activity "
                                     + r.intent.getComponent().flattenToShortString());
                             r.stack.finishActivityLocked(r, index,
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index 72ea7ce..e29da1c 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -321,6 +321,15 @@
         }
     }
 
+    void makeFinishing() {
+        if (!finishing) {
+            finishing = true;
+            if (task != null) {
+                task.numActivities--;
+            }
+        }
+    }
+
     UriPermissionOwner getUriPermissionsLocked() {
         if (uriPermissions == null) {
             uriPermissions = new UriPermissionOwner(service, this);
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index eee9f7e..bc00478 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -50,7 +50,6 @@
 import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.Binder;
-import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
@@ -3071,7 +3070,7 @@
             return false;
         }
 
-        r.finishing = true;
+        r.makeFinishing();
         EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
                 System.identityHashCode(r),
                 r.task.taskId, r.shortComponentName, reason);
@@ -3276,6 +3275,7 @@
 
     private final void removeActivityFromHistoryLocked(ActivityRecord r) {
         if (r.state != ActivityState.DESTROYED) {
+            r.makeFinishing();
             mHistory.remove(r);
             r.inHistory = false;
             r.state = ActivityState.DESTROYED;
@@ -3440,6 +3440,7 @@
             ActivityRecord hr = (ActivityRecord)mHistory.get(i);
             if (hr.isHomeActivity) {
                 homeTask = hr.task;
+                break;
             }
         }
         if (homeTask != null) {
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index 8a021cb..0c1fcf9 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -503,12 +503,18 @@
 
 void LayerBase::setBufferCrop(const Rect& crop) {
     if (!crop.isEmpty()) {
-        mBufferCrop = crop;
+        if (mBufferCrop != crop) {
+            mBufferCrop = crop;
+            mFlinger->invalidateHwcGeometry();
+        }
     }
 }
 
 void LayerBase::setBufferTransform(uint32_t transform) {
-    mBufferTransform = transform;
+    if (mBufferTransform != transform) {
+        mBufferTransform = transform;
+        mFlinger->invalidateHwcGeometry();
+    }
 }
 
 void LayerBase::dump(String8& result, char* buffer, size_t SIZE) const
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 967ff1a..77695d7 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -465,7 +465,7 @@
         handleTransactionLocked(transactionFlags, ditchedLayers);
         mLastTransactionTime = systemTime() - now;
         mDebugInTransaction = 0;
-        mHwWorkListDirty = true;
+        invalidateHwcGeometry();
         // here the transaction has been committed
     }
 
@@ -731,13 +731,18 @@
 
             mWormholeRegion = screenRegion.subtract(opaqueRegion);
             mVisibleRegionsDirty = false;
-            mHwWorkListDirty = true;
+            invalidateHwcGeometry();
         }
 
     unlockPageFlip(currentLayers);
     mDirtyRegion.andSelf(screenRegion);
 }
 
+void SurfaceFlinger::invalidateHwcGeometry()
+{
+    mHwWorkListDirty = true;
+}
+
 bool SurfaceFlinger::lockPageFlip(const LayerVector& currentLayers)
 {
     bool recomputeVisibleRegions = false;
@@ -1591,7 +1596,7 @@
             case 1008:  // toggle use of hw composer
                 n = data.readInt32();
                 mDebugDisableHWC = n ? 1 : 0;
-                mHwWorkListDirty = true;
+                invalidateHwcGeometry();
                 // fall-through...
             case 1004:{ // repaint everything
                 Mutex::Autolock _l(mStateLock);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 2f2977a..2591123 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -225,6 +225,7 @@
     status_t removeLayer(const sp<LayerBase>& layer);
     status_t addLayer(const sp<LayerBase>& layer);
     status_t invalidateLayerVisibility(const sp<LayerBase>& layer);
+    void invalidateHwcGeometry();
 
     sp<Layer> getLayer(const sp<ISurface>& sur) const;
 
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 615870b..2e4199e 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -496,8 +496,17 @@
         throw new UnsupportedOperationException();
     }
 
-    @Override
     public void setPackageObbPath(String packageName, String path) {
         throw new UnsupportedOperationException();
     }
+
+    @Override
+    public void setPackageObbPaths(String packageName, String[] paths) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public String[] getPackageObbPaths(String packageName) {
+        throw new UnsupportedOperationException();
+    }
 }
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
index 4982c46..e5a46b9 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LoadTestsAutoTest.java
@@ -93,11 +93,8 @@
         final VMRuntime runtime = VMRuntime.getRuntime();
 
         runtime.gcSoftReferences();
-        runtime.runFinalizationSync();
         runtime.gcSoftReferences();
-        runtime.runFinalizationSync();
         runtime.gcSoftReferences();
-        runtime.runFinalizationSync();
         Runtime.getRuntime().runFinalization();
         Runtime.getRuntime().gc();
         Runtime.getRuntime().gc();
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index 0d9efba..8bfaf40 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -1009,7 +1009,7 @@
     /*package*/ static void native_drawTextRun(int nativeCanvas, char[] text,
             int start, int count, int contextStart, int contextCount,
             float x, float y, int flags, int paint) {
-        native_drawText(nativeCanvas, text, 0, count, x, y, flags, paint);
+        native_drawText(nativeCanvas, text, start, count, x, y, flags, paint);
     }
 
     /*package*/ static void native_drawPosText(int nativeCanvas,
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index dc027b7..f5fc036 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -254,6 +254,11 @@
             return null;
         }
 
+        // needed by SearchView
+        if (INPUT_METHOD_SERVICE.equals(service)) {
+            return null;
+        }
+
         throw new UnsupportedOperationException("Unsupported Service: " + service);
     }
 
@@ -443,7 +448,7 @@
                 } else {
                     // there is a value in the XML, but we need to resolve it in case it's
                     // referencing another resource or a theme value.
-                    ta.bridgeSetValue(index, name, resolveValue(null, name, value));
+                    ta.bridgeSetValue(index, name, resolveValue(null, name, value, isPlatformFile));
                 }
             }
         }
@@ -506,21 +511,24 @@
      * @param type the type of the resource
      * @param name the name of the attribute containing this value.
      * @param value the resource value, or reference to resolve
+     * @param isFrameworkValue whether the value is a framework value.
+     *
      * @return the resolved resource value or <code>null</code> if it failed to resolve it.
      */
-    private ResourceValue resolveValue(String type, String name, String value) {
+    private ResourceValue resolveValue(String type, String name, String value,
+            boolean isFrameworkValue) {
         if (value == null) {
             return null;
         }
 
         // get the ResourceValue referenced by this value
-        ResourceValue resValue = findResValue(value, false /*forceFrameworkOnly*/);
+        ResourceValue resValue = findResValue(value, isFrameworkValue);
 
         // if resValue is null, but value is not null, this means it was not a reference.
         // we return the name/value wrapper in a ResourceValue. the isFramework flag doesn't
         // matter.
         if (resValue == null) {
-            return new ResourceValue(type, name, value, false /*isFramework*/);
+            return new ResourceValue(type, name, value, isFrameworkValue);
         }
 
         // we resolved a first reference, but we need to make sure this isn't a reference also.
@@ -701,6 +709,15 @@
             if (item != null) {
                 return item;
             }
+
+            // if it was not found and the type is an id, it is possible that the ID was
+            // generated dynamically when compiling the framework resources.
+            // Look for it in the R map.
+            if (BridgeConstants.RES_ID.equals(resType)) {
+                if (Bridge.getResourceValue(resType, resName) != null) {
+                    return new ResourceValue(resType, resName, true);
+                }
+            }
         }
 
         // didn't find the resource anywhere.
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java
index b3f1fff..c4ebb8a 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java
@@ -393,27 +393,26 @@
      * @param bitmap the bitmap to link to.
      */
     public void setBitmap(Bitmap_Delegate bitmap) {
-        assert mLayers.size() == 0;
-
         // create a new Layer for the bitmap. This will be the base layer.
         Graphics2D graphics2D = bitmap.getImage().createGraphics();
         Layer baseLayer = new Layer(graphics2D, bitmap);
 
-        // add it to the list.
+        // Set the current transform and clip which can either come from mTransform/mClip if they
+        // were set when there was no bitmap/layers or from the current base layers if there is
+        // one already.
+
+        graphics2D.setTransform(getTransform());
+        // reset mTransform in case there was one.
+        mTransform = null;
+
+        baseLayer.setClip(getClip());
+        // reset mClip in case there was one.
+        mClip = null;
+
+        // replace whatever current layers we have with this.
+        mLayers.clear();
         mLayers.add(baseLayer);
 
-        // if transform and clip where modified before, get the information and give it to the
-        // layer.
-
-        if (mTransform != null) {
-            graphics2D.setTransform(mTransform);
-            mTransform = null;
-        }
-
-        if (mClip != null) {
-            baseLayer.setClip(mClip);
-            mClip = null;
-        }
     }
 
     public void translate(float dx, float dy) {