Merge change 2355

* changes:
  add Gservices setting for "send message using bareJid timeout".
diff --git a/Android.mk b/Android.mk
index 8c81b8e..ca41e2f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -150,6 +150,8 @@
 	telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl \
 	telephony/java/com/android/internal/telephony/IIccPhoneBook.aidl \
 	telephony/java/com/android/internal/telephony/ISms.aidl \
+	tts/java/android/tts/ITtsCallback.aidl \
+	tts/java/android/tts/ITts.aidl \
 	wifi/java/android/net/wifi/IWifiManager.aidl \
 	telephony/java/com/android/internal/telephony/IExtendedNetworkService.aidl
 
@@ -346,7 +348,7 @@
 # most current Android platform version included in the SDK package. 
 framework_docs_SDK_VERSION :=  1.5
 # release version for SDK (ie "Release x")
-framework_docs_SDK_REL_ID :=   1
+framework_docs_SDK_REL_ID :=   2
 framework_docs_SDK_CURRENT_DIR := $(framework_docs_SDK_VERSION)_r$(framework_docs_SDK_REL_ID)
 
 framework_docs_LOCAL_DROIDDOC_OPTIONS += \
diff --git a/api/current.xml b/api/current.xml
index b15703a..4db6e66 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -2037,7 +2037,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843433"
+ value="16843424"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -2994,7 +2994,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="16843434"
+ value="16843425"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -3595,83 +3595,6 @@
  visibility="public"
 >
 </field>
-<field name="donut_resource_pad33"
- type="int"
- transient="false"
- volatile="false"
- value="16843391"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad34"
- type="int"
- transient="false"
- volatile="false"
- value="16843390"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad35"
- type="int"
- transient="false"
- volatile="false"
- value="16843389"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad36"
- type="int"
- transient="false"
- volatile="false"
- value="16843388"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad37"
- type="int"
- transient="false"
- volatile="false"
- value="16843387"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad38"
- type="int"
- transient="false"
- volatile="false"
- value="16843386"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad39"
- type="int"
- transient="false"
- volatile="false"
- value="16843385"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="donut_resource_pad4"
  type="int"
  transient="false"
@@ -3683,61 +3606,6 @@
  visibility="public"
 >
 </field>
-<field name="donut_resource_pad40"
- type="int"
- transient="false"
- volatile="false"
- value="16843384"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad41"
- type="int"
- transient="false"
- volatile="false"
- value="16843383"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad42"
- type="int"
- transient="false"
- volatile="false"
- value="16843382"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad43"
- type="int"
- transient="false"
- volatile="false"
- value="16843381"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="donut_resource_pad44"
- type="int"
- transient="false"
- volatile="false"
- value="16843380"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 <field name="donut_resource_pad5"
  type="int"
  transient="false"
@@ -4090,6 +3958,17 @@
  visibility="public"
 >
 </field>
+<field name="eventsInterceptionEnabled"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843390"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="excludeFromRecents"
  type="int"
  transient="false"
@@ -4211,6 +4090,39 @@
  visibility="public"
 >
 </field>
+<field name="fadeDuration"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843384"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="fadeEnabled"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843391"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="fadeOffset"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843383"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="fadingEdge"
  type="int"
  transient="false"
@@ -4530,6 +4442,83 @@
  visibility="public"
 >
 </field>
+<field name="gestureColor"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843381"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="gestureStrokeAngleThreshold"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843389"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="gestureStrokeLengthThreshold"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843387"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="gestureStrokeSquarenessThreshold"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843388"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="gestureStrokeType"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843386"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="gestureStrokeWidth"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843380"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="gestures"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843385"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="gradientRadius"
  type="int"
  transient="false"
@@ -8930,6 +8919,17 @@
  visibility="public"
 >
 </field>
+<field name="uncertainGestureColor"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843382"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="unselectedAlpha"
  type="int"
  transient="false"
@@ -28053,36 +28053,6 @@
 <parameter name="values" type="android.content.ContentValues[]">
 </parameter>
 </method>
-<method name="bulkInsertEntities"
- return="android.net.Uri[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="uri" type="android.net.Uri">
-</parameter>
-<parameter name="entities" type="android.content.Entity[]">
-</parameter>
-</method>
-<method name="bulkUpdateEntities"
- return="int[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="uri" type="android.net.Uri">
-</parameter>
-<parameter name="entities" type="android.content.Entity[]">
-</parameter>
-</method>
 <method name="delete"
  return="int"
  abstract="true"
@@ -28382,6 +28352,23 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<method name="applyBatch"
+ return="android.content.ContentProviderResult[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="operations" type="android.content.ContentProviderOperation[]">
+</parameter>
+<exception name="OperationApplicationException" type="android.content.OperationApplicationException">
+</exception>
+<exception name="RemoteException" type="android.os.RemoteException">
+</exception>
+</method>
 <method name="bulkInsert"
  return="int"
  abstract="false"
@@ -28399,40 +28386,6 @@
 <exception name="RemoteException" type="android.os.RemoteException">
 </exception>
 </method>
-<method name="bulkInsertEntities"
- return="android.net.Uri[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="uri" type="android.net.Uri">
-</parameter>
-<parameter name="entities" type="android.content.Entity[]">
-</parameter>
-<exception name="RemoteException" type="android.os.RemoteException">
-</exception>
-</method>
-<method name="bulkUpdateEntities"
- return="int[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="uri" type="android.net.Uri">
-</parameter>
-<parameter name="entities" type="android.content.Entity[]">
-</parameter>
-<exception name="RemoteException" type="android.os.RemoteException">
-</exception>
-</method>
 <method name="delete"
  return="int"
  abstract="false"
@@ -28652,6 +28605,8 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.os.Parcelable">
+</implements>
 <method name="apply"
  return="android.content.ContentProviderResult"
  abstract="false"
@@ -28671,6 +28626,50 @@
 <exception name="OperationApplicationException" type="android.content.OperationApplicationException">
 </exception>
 </method>
+<method name="describeContents"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getUri"
+ return="android.net.Uri"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isReadOperation"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isWriteOperation"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="newCountQuery"
  return="android.content.ContentProviderOperation.Builder"
  abstract="false"
@@ -28753,6 +28752,31 @@
 <parameter name="numBackRefs" type="int">
 </parameter>
 </method>
+<method name="writeToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dest" type="android.os.Parcel">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<field name="CREATOR"
+ type="android.os.Parcelable.Creator"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <class name="ContentProviderOperation.Builder"
  extends="java.lang.Object"
@@ -28773,6 +28797,19 @@
  visibility="public"
 >
 </method>
+<method name="withEntity"
+ return="android.content.ContentProviderOperation.Builder"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="entity" type="android.content.Entity">
+</parameter>
+</method>
 <method name="withExpectedCount"
  return="android.content.ContentProviderOperation.Builder"
  abstract="false"
@@ -28849,6 +28886,8 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<implements name="android.os.Parcelable">
+</implements>
 <constructor name="ContentProviderResult"
  type="android.content.ContentProviderResult"
  static="false"
@@ -28869,6 +28908,52 @@
 <parameter name="count" type="int">
 </parameter>
 </constructor>
+<constructor name="ContentProviderResult"
+ type="android.content.ContentProviderResult"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="source" type="android.os.Parcel">
+</parameter>
+</constructor>
+<method name="describeContents"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="writeToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="dest" type="android.os.Parcel">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<field name="CREATOR"
+ type="android.os.Parcelable.Creator"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="count"
  type="java.lang.Integer"
  transient="false"
@@ -29018,6 +29103,25 @@
 <parameter name="name" type="java.lang.String">
 </parameter>
 </method>
+<method name="applyBatch"
+ return="android.content.ContentProviderResult[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="authority" type="java.lang.String">
+</parameter>
+<parameter name="operations" type="android.content.ContentProviderOperation[]">
+</parameter>
+<exception name="OperationApplicationException" type="android.content.OperationApplicationException">
+</exception>
+<exception name="RemoteException" type="android.os.RemoteException">
+</exception>
+</method>
 <method name="bulkInsert"
  return="int"
  abstract="false"
@@ -29033,40 +29137,6 @@
 <parameter name="values" type="android.content.ContentValues[]">
 </parameter>
 </method>
-<method name="bulkInsertEntities"
- return="android.net.Uri[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="uri" type="android.net.Uri">
-</parameter>
-<parameter name="entities" type="android.content.Entity[]">
-</parameter>
-<exception name="RemoteException" type="android.os.RemoteException">
-</exception>
-</method>
-<method name="bulkUpdateEntities"
- return="int[]"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="uri" type="android.net.Uri">
-</parameter>
-<parameter name="entities" type="android.content.Entity[]">
-</parameter>
-<exception name="RemoteException" type="android.os.RemoteException">
-</exception>
-</method>
 <method name="cancelSync"
  return="void"
  abstract="false"
@@ -29276,7 +29346,7 @@
 <parameter name="sortOrder" type="java.lang.String">
 </parameter>
 </method>
-<method name="queryEntity"
+<method name="queryEntities"
  return="android.content.EntityIterator"
  abstract="false"
  native="false"
@@ -32604,119 +32674,6 @@
 </exception>
 </method>
 </interface>
-<interface name="IEntityIterator"
- abstract="true"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<implements name="android.os.IInterface">
-</implements>
-<method name="close"
- return="void"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="RemoteException" type="android.os.RemoteException">
-</exception>
-</method>
-<method name="hasNext"
- return="boolean"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="RemoteException" type="android.os.RemoteException">
-</exception>
-</method>
-<method name="next"
- return="android.content.Entity"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<exception name="RemoteException" type="android.os.RemoteException">
-</exception>
-</method>
-</interface>
-<class name="IEntityIterator.Stub"
- extends="android.os.Binder"
- abstract="true"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<implements name="android.content.IEntityIterator">
-</implements>
-<constructor name="IEntityIterator.Stub"
- type="android.content.IEntityIterator.Stub"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</constructor>
-<method name="asBinder"
- return="android.os.IBinder"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
-<method name="asInterface"
- return="android.content.IEntityIterator"
- abstract="false"
- native="false"
- synchronized="false"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="obj" type="android.os.IBinder">
-</parameter>
-</method>
-<method name="onTransact"
- return="boolean"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="code" type="int">
-</parameter>
-<parameter name="data" type="android.os.Parcel">
-</parameter>
-<parameter name="reply" type="android.os.Parcel">
-</parameter>
-<parameter name="flags" type="int">
-</parameter>
-<exception name="RemoteException" type="android.os.RemoteException">
-</exception>
-</method>
-</class>
 <class name="Intent"
  extends="java.lang.Object"
  abstract="false"
@@ -46712,6 +46669,21 @@
 <exception name="FileNotFoundException" type="java.io.FileNotFoundException">
 </exception>
 </method>
+<method name="readExceptionWithOperationApplicationExceptionFromParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="reply" type="android.os.Parcel">
+</parameter>
+<exception name="OperationApplicationException" type="android.content.OperationApplicationException">
+</exception>
+</method>
 <method name="sqlEscapeString"
  return="java.lang.String"
  abstract="false"
@@ -49368,6 +49340,1338 @@
 </method>
 </class>
 </package>
+<package name="android.gesture"
+>
+<class name="Gesture"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<implements name="android.os.Parcelable">
+</implements>
+<constructor name="Gesture"
+ type="android.gesture.Gesture"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="addStroke"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="stroke" type="android.gesture.GestureStroke">
+</parameter>
+</method>
+<method name="describeContents"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getBoundingBox"
+ return="android.graphics.RectF"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getID"
+ return="long"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getLength"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getStrokes"
+ return="java.util.ArrayList&lt;android.gesture.GestureStroke&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getStrokesCount"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="toBitmap"
+ return="android.graphics.Bitmap"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="width" type="int">
+</parameter>
+<parameter name="height" type="int">
+</parameter>
+<parameter name="edge" type="int">
+</parameter>
+<parameter name="numSample" type="int">
+</parameter>
+<parameter name="color" type="int">
+</parameter>
+</method>
+<method name="toBitmap"
+ return="android.graphics.Bitmap"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="width" type="int">
+</parameter>
+<parameter name="height" type="int">
+</parameter>
+<parameter name="edge" type="int">
+</parameter>
+<parameter name="color" type="int">
+</parameter>
+</method>
+<method name="toPath"
+ return="android.graphics.Path"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="toPath"
+ return="android.graphics.Path"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="path" type="android.graphics.Path">
+</parameter>
+</method>
+<method name="toPath"
+ return="android.graphics.Path"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="width" type="int">
+</parameter>
+<parameter name="height" type="int">
+</parameter>
+<parameter name="edge" type="int">
+</parameter>
+<parameter name="numSample" type="int">
+</parameter>
+</method>
+<method name="toPath"
+ return="android.graphics.Path"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="path" type="android.graphics.Path">
+</parameter>
+<parameter name="width" type="int">
+</parameter>
+<parameter name="height" type="int">
+</parameter>
+<parameter name="edge" type="int">
+</parameter>
+<parameter name="numSample" type="int">
+</parameter>
+</method>
+<method name="writeToParcel"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="out" type="android.os.Parcel">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<field name="CREATOR"
+ type="android.os.Parcelable.Creator"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="GestureLibrary"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GestureLibrary"
+ type="android.gesture.GestureLibrary"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="path" type="java.lang.String">
+</parameter>
+</constructor>
+<method name="addGesture"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="entryName" type="java.lang.String">
+</parameter>
+<parameter name="gesture" type="android.gesture.Gesture">
+</parameter>
+</method>
+<method name="getGestureEntries"
+ return="java.util.Set&lt;java.lang.String&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getGestures"
+ return="java.util.ArrayList&lt;android.gesture.Gesture&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="entryName" type="java.lang.String">
+</parameter>
+</method>
+<method name="getOrientationStyle"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getSequenceType"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="load"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="recognize"
+ return="java.util.ArrayList&lt;android.gesture.Prediction&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="gesture" type="android.gesture.Gesture">
+</parameter>
+</method>
+<method name="removeEntry"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="entryName" type="java.lang.String">
+</parameter>
+</method>
+<method name="removeGesture"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="entryName" type="java.lang.String">
+</parameter>
+<parameter name="gesture" type="android.gesture.Gesture">
+</parameter>
+</method>
+<method name="save"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="setOrientationStyle"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="style" type="int">
+</parameter>
+</method>
+<method name="setSequenceType"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="type" type="int">
+</parameter>
+</method>
+<field name="ORIENTATION_INVARIANT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ORIENTATION_SENSITIVE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SEQUENCE_INVARIANT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SEQUENCE_SENSITIVE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="GestureOverlayView"
+ extends="android.widget.FrameLayout"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GestureOverlayView"
+ type="android.gesture.GestureOverlayView"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+</constructor>
+<constructor name="GestureOverlayView"
+ type="android.gesture.GestureOverlayView"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+</constructor>
+<constructor name="GestureOverlayView"
+ type="android.gesture.GestureOverlayView"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="attrs" type="android.util.AttributeSet">
+</parameter>
+<parameter name="defStyle" type="int">
+</parameter>
+</constructor>
+<method name="addOnGestureListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.gesture.GestureOverlayView.OnGestureListener">
+</parameter>
+</method>
+<method name="addOnGesturePerformedListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.gesture.GestureOverlayView.OnGesturePerformedListener">
+</parameter>
+</method>
+<method name="cancelClearAnimation"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="cancelGesture"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="clear"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="animated" type="boolean">
+</parameter>
+</method>
+<method name="getCurrentStroke"
+ return="java.util.ArrayList&lt;android.gesture.GesturePoint&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getGesture"
+ return="android.gesture.Gesture"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getGestureColor"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getGestureStrokeAngleThreshold"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getGestureStrokeLengthThreshold"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getGestureStrokeSquarenessTreshold"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getGestureStrokeType"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getGestureStrokeWidth"
+ return="float"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getOrientation"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getUncertainGestureColor"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isEventsInterceptionEnabled"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isFadeEnabled"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isGesturing"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="removeAllOnGestureListeners"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="removeAllOnGesturePerformedListeners"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="removeOnGestureListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.gesture.GestureOverlayView.OnGestureListener">
+</parameter>
+</method>
+<method name="removeOnGesturePerformedListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.gesture.GestureOverlayView.OnGesturePerformedListener">
+</parameter>
+</method>
+<method name="setEventsInterceptionEnabled"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enabled" type="boolean">
+</parameter>
+</method>
+<method name="setFadeEnabled"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="fadeEnabled" type="boolean">
+</parameter>
+</method>
+<method name="setGesture"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="gesture" type="android.gesture.Gesture">
+</parameter>
+</method>
+<method name="setGestureColor"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="color" type="int">
+</parameter>
+</method>
+<method name="setGestureStrokeAngleThreshold"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="gestureStrokeAngleThreshold" type="float">
+</parameter>
+</method>
+<method name="setGestureStrokeLengthThreshold"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="gestureStrokeLengthThreshold" type="float">
+</parameter>
+</method>
+<method name="setGestureStrokeSquarenessTreshold"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="gestureStrokeSquarenessTreshold" type="float">
+</parameter>
+</method>
+<method name="setGestureStrokeType"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="gestureStrokeType" type="int">
+</parameter>
+</method>
+<method name="setGestureStrokeWidth"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="gestureStrokeWidth" type="float">
+</parameter>
+</method>
+<method name="setOrientation"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="orientation" type="int">
+</parameter>
+</method>
+<method name="setUncertainGestureColor"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="color" type="int">
+</parameter>
+</method>
+<field name="GESTURE_STROKE_TYPE_MULTIPLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GESTURE_STROKE_TYPE_SINGLE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ORIENTATION_HORIZONTAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="ORIENTATION_VERTICAL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<interface name="GestureOverlayView.OnGestureListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onGesture"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="overlay" type="android.gesture.GestureOverlayView">
+</parameter>
+<parameter name="event" type="android.view.MotionEvent">
+</parameter>
+</method>
+<method name="onGestureCancelled"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="overlay" type="android.gesture.GestureOverlayView">
+</parameter>
+<parameter name="event" type="android.view.MotionEvent">
+</parameter>
+</method>
+<method name="onGestureEnded"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="overlay" type="android.gesture.GestureOverlayView">
+</parameter>
+<parameter name="event" type="android.view.MotionEvent">
+</parameter>
+</method>
+<method name="onGestureStarted"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="overlay" type="android.gesture.GestureOverlayView">
+</parameter>
+<parameter name="event" type="android.view.MotionEvent">
+</parameter>
+</method>
+</interface>
+<interface name="GestureOverlayView.OnGesturePerformedListener"
+ abstract="true"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="onGesturePerformed"
+ return="void"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="overlay" type="android.gesture.GestureOverlayView">
+</parameter>
+<parameter name="gesture" type="android.gesture.Gesture">
+</parameter>
+</method>
+</interface>
+<class name="GesturePoint"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GesturePoint"
+ type="android.gesture.GesturePoint"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="x" type="float">
+</parameter>
+<parameter name="y" type="float">
+</parameter>
+<parameter name="t" type="long">
+</parameter>
+</constructor>
+<field name="timestamp"
+ type="long"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="x"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="y"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="GestureStroke"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="GestureStroke"
+ type="android.gesture.GestureStroke"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="points" type="java.util.ArrayList&lt;android.gesture.GesturePoint&gt;">
+</parameter>
+</constructor>
+<method name="clearPath"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="computeOrientedBoundingBox"
+ return="android.gesture.OrientedBoundingBox"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="getPath"
+ return="android.graphics.Path"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="toPath"
+ return="android.graphics.Path"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="width" type="float">
+</parameter>
+<parameter name="height" type="float">
+</parameter>
+<parameter name="numSample" type="int">
+</parameter>
+</method>
+<field name="boundingBox"
+ type="android.graphics.RectF"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="length"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="points"
+ type="float[]"
+ transient="false"
+ volatile="false"
+ value="null"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="LetterRecognizer"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="getLetterRecognizer"
+ return="android.gesture.LetterRecognizer"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="context" type="android.content.Context">
+</parameter>
+<parameter name="type" type="int">
+</parameter>
+</method>
+<method name="recognize"
+ return="java.util.ArrayList&lt;android.gesture.Prediction&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="gesture" type="android.gesture.Gesture">
+</parameter>
+</method>
+<method name="recognize"
+ return="java.util.ArrayList&lt;android.gesture.Prediction&gt;"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="gesture" type="android.gesture.Gesture">
+</parameter>
+<parameter name="predictions" type="java.util.ArrayList&lt;android.gesture.Prediction&gt;">
+</parameter>
+</method>
+<field name="RECOGNIZER_LATIN_LOWERCASE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="OrientedBoundingBox"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<field name="centerX"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="centerY"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="height"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="orientation"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="squareness"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="width"
+ type="float"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="Prediction"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<field name="name"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="score"
+ type="double"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+</package>
 <package name="android.graphics"
 >
 <class name="AvoidXfermode"
@@ -72937,6 +74241,17 @@
  visibility="public"
 >
 </constructor>
+<method name="getAudioSourceMax"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getMaxAmplitude"
  return="int"
  abstract="false"
@@ -73338,6 +74653,39 @@
  visibility="public"
 >
 </field>
+<field name="VOICE_CALL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="VOICE_DOWNLINK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="3"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="VOICE_UPLINK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 </class>
 <interface name="MediaRecorder.OnErrorListener"
  abstract="true"
@@ -91849,6 +93197,16 @@
  visibility="public"
 >
 </field>
+<field name="CPU_ABI"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="DEVICE"
  type="java.lang.String"
  transient="false"
@@ -161759,6 +163117,17 @@
  visibility="public"
 >
 </method>
+<method name="getGestures"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getListPaddingBottom"
  return="int"
  abstract="false"
@@ -162132,6 +163501,19 @@
 <parameter name="filterText" type="java.lang.String">
 </parameter>
 </method>
+<method name="setGestures"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="gestures" type="int">
+</parameter>
+</method>
 <method name="setOnScrollListener"
  return="void"
  abstract="false"
@@ -162277,6 +163659,39 @@
 <parameter name="dr" type="android.graphics.drawable.Drawable">
 </parameter>
 </method>
+<field name="GESTURES_FILTER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GESTURES_JUMP"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="GESTURES_NONE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="TRANSCRIPT_MODE_ALWAYS_SCROLL"
  type="int"
  transient="false"
@@ -170986,6 +172401,21 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="width" type="int">
+</parameter>
+<parameter name="height" type="int">
+</parameter>
+</method>
+<method name="update"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
 <parameter name="x" type="int">
 </parameter>
 <parameter name="y" type="int">
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index 8207da6..404512e 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -1084,7 +1084,6 @@
     status_t err = BnCameraService::onTransact(code, data, reply, flags);
 
 #if DEBUG_HEAP_LEAKS
-
     LOGD("+++ onTransact err %d code %d", err, code);
 
     if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
@@ -1121,6 +1120,7 @@
         }
     }
 #endif // DEBUG_HEAP_LEAKS
+
     return err;
 }
 
diff --git a/cmds/bootanimation/Android.mk b/cmds/bootanimation/Android.mk
new file mode 100644
index 0000000..9c94c2e
--- /dev/null
+++ b/cmds/bootanimation/Android.mk
@@ -0,0 +1,30 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	bootanimation_main.cpp \
+	BootAnimation.cpp
+
+# need "-lrt" on Linux simulator to pick up clock_gettime
+ifeq ($(TARGET_SIMULATOR),true)
+	ifeq ($(HOST_OS),linux)
+		LOCAL_LDLIBS += -lrt
+	endif
+endif
+
+LOCAL_SHARED_LIBRARIES := \
+	libcutils \
+	libutils \
+    libui \
+	libcorecg \
+	libsgl \
+    libEGL \
+    libGLESv1_CM
+
+LOCAL_C_INCLUDES := \
+	$(call include-path-for, corecg graphics)
+
+LOCAL_MODULE:= bootanimation
+
+
+include $(BUILD_EXECUTABLE)
diff --git a/libs/surfaceflinger/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
similarity index 94%
rename from libs/surfaceflinger/BootAnimation.cpp
rename to cmds/bootanimation/BootAnimation.cpp
index db40385..d565dc1 100644
--- a/libs/surfaceflinger/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -22,6 +22,7 @@
 #include <fcntl.h>
 #include <utils/misc.h>
 
+#include <binder/IPCThreadState.h>
 #include <utils/threads.h>
 #include <utils/Atomic.h>
 #include <utils/Errors.h>
@@ -49,10 +50,9 @@
 
 // ---------------------------------------------------------------------------
 
-BootAnimation::BootAnimation(const sp<ISurfaceComposer>& composer) :
-    Thread(false) {
-    mSession = SurfaceComposerClient::clientForConnection(
-            composer->createConnection()->asBinder());
+BootAnimation::BootAnimation() : Thread(false)
+{    
+    mSession = new SurfaceComposerClient();
 }
 
 BootAnimation::~BootAnimation() {
@@ -131,7 +131,7 @@
 
     // create the native surface
     sp<Surface> s = session()->createSurface(getpid(), 0, dinfo.w, dinfo.h,
-            PIXEL_FORMAT_RGB_565);
+            PIXEL_FORMAT_RGB_565, ISurfaceComposer::eGPU);
     session()->openTransaction();
     s->setLayer(0x40000000);
     session()->closeTransaction();
@@ -144,7 +144,10 @@
     EGLConfig config;
     EGLSurface surface;
     EGLContext context;
+
     EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+
+    eglInitialize(display, 0, 0);
     eglChooseConfig(display, attribs, &config, 1, &numConfigs);
 
     mNativeWindowSurface = new EGLNativeWindowSurface(s);
@@ -170,17 +173,15 @@
     return NO_ERROR;
 }
 
-void BootAnimation::requestExit() {
-    mBarrier.open();
-    Thread::requestExit();
-}
-
 bool BootAnimation::threadLoop() {
     bool r = android();
     eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
     eglDestroyContext(mDisplay, mContext);
     eglDestroySurface(mDisplay, mSurface);
     mNativeWindowSurface.clear();
+    mFlingerSurface.clear();
+    eglTerminate(mDisplay);
+    IPCThreadState::self()->stopProcess();
     return r;
 }
 
@@ -227,8 +228,10 @@
         glBindTexture(GL_TEXTURE_2D, mAndroid[0].name);
         glDrawTexiOES(xc, yc, 0, mAndroid[0].w, mAndroid[0].h);
 
-        eglSwapBuffers(mDisplay, mSurface);
-        
+        EGLBoolean res = eglSwapBuffers(mDisplay, mSurface);
+        if (res == EGL_FALSE)
+            break;
+
         // 12fps: don't animate too fast to preserve CPU
         const nsecs_t sleepTime = 83333 - ns2us(systemTime() - now);
         if (sleepTime > 0)
diff --git a/libs/surfaceflinger/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
similarity index 92%
rename from libs/surfaceflinger/BootAnimation.h
rename to cmds/bootanimation/BootAnimation.h
index 3fb6670..42e9eed 100644
--- a/libs/surfaceflinger/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -29,8 +29,6 @@
 #include <EGL/egl.h>
 #include <GLES/gl.h>
 
-#include "Barrier.h"
-
 class SkBitmap;
 
 namespace android {
@@ -43,11 +41,10 @@
 class BootAnimation : public Thread
 {
 public:
-                BootAnimation(const sp<ISurfaceComposer>& composer);
+                BootAnimation();
     virtual     ~BootAnimation();
 
     const sp<SurfaceComposerClient>& session() const;
-    virtual void        requestExit();
 
 private:
     virtual bool        threadLoop();
@@ -73,7 +70,6 @@
     EGLDisplay  mSurface;
     sp<Surface> mFlingerSurface;
     sp<EGLNativeWindowSurface> mNativeWindowSurface;
-    Barrier mBarrier;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/cmds/bootanimation/bootanimation_main.cpp b/cmds/bootanimation/bootanimation_main.cpp
new file mode 100644
index 0000000..346f156
--- /dev/null
+++ b/cmds/bootanimation/bootanimation_main.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BootAnimation"
+
+#include <binder/IPCThreadState.h>
+#include <binder/ProcessState.h>
+#include <binder/IServiceManager.h>
+#include <utils/Log.h>
+#include <utils/threads.h>
+
+#include <ui/ISurfaceComposer.h>
+
+#if defined(HAVE_PTHREADS)
+# include <pthread.h>
+# include <sys/resource.h>
+#endif
+
+#include "BootAnimation.h"
+
+using namespace android;
+
+// ---------------------------------------------------------------------------
+
+int main(int argc, char** argv)
+{
+#if defined(HAVE_PTHREADS)
+    setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DISPLAY);
+#endif
+
+    sp<ProcessState> proc(ProcessState::self());
+    ProcessState::self()->startThreadPool();
+
+    // create the boot animation object
+    sp<BootAnimation> boot = new BootAnimation();
+
+    IPCThreadState::self()->joinThreadPool();
+    return 0;
+}
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index eabf98e..cc951c1 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -165,6 +165,7 @@
     int c, fd, vibrate_fd, fds[2];
     char path[PATH_MAX];
     pid_t   pid;
+    gid_t groups[] = { AID_LOG, AID_SDCARD_RW };
 
     /* set as high priority, and protect from OOM killer */
     setpriority(PRIO_PROCESS, 0, -20);
@@ -207,7 +208,7 @@
         vibrate_fd = -1;
 
     /* switch to non-root user and group */
-    setgid(AID_LOG);
+    setgroups(sizeof(groups)/sizeof(groups[0]), groups);
     setuid(AID_SHELL);
 
     /* make it safe to use both printf and STDOUT_FILENO */ 
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index 8212b92..fd9e708 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -543,6 +543,9 @@
         case PackageManager.INSTALL_FAILED_TEST_ONLY:
             s = "INSTALL_FAILED_TEST_ONLY";
             break;
+        case PackageManager.INSTALL_FAILED_CPU_ABI_INCOMPATIBLE:
+            s = "INSTALL_FAILED_CPU_ABI_INCOMPATIBLE";
+            break;
         case PackageManager.INSTALL_PARSE_FAILED_NOT_APK:
             s = "INSTALL_PARSE_FAILED_NOT_APK";
             break;
diff --git a/cmds/runtime/ServiceManager.h b/cmds/runtime/ServiceManager.h
index d09cec8..090ca6d 100644
--- a/cmds/runtime/ServiceManager.h
+++ b/cmds/runtime/ServiceManager.h
@@ -4,7 +4,7 @@
 #ifndef ANDROID_SERVICE_MANAGER_H
 #define ANDROID_SERVICE_MANAGER_H
 
-#include <utils/IServiceManager.h>
+#include <binder/IServiceManager.h>
 #include <utils/KeyedVector.h>
 #include <utils/threads.h>
 
diff --git a/cmds/runtime/main_runtime.cpp b/cmds/runtime/main_runtime.cpp
index 718ea67..6ae3a5c 100644
--- a/cmds/runtime/main_runtime.cpp
+++ b/cmds/runtime/main_runtime.cpp
@@ -45,9 +45,9 @@
     "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,3001,3002,3003",
     /* CAP_SYS_TTY_CONFIG & CAP_SYS_RESOURCE & CAP_NET_BROADCAST &
      * CAP_NET_ADMIN & CAP_NET_RAW & CAP_NET_BIND_SERVICE  & CAP_KILL &
-     * CAP_SYS_BOOT
+     * CAP_SYS_BOOT CAP_SYS_NICE
      */
-    "--capabilities=88161312,88161312",
+    "--capabilities=96549920,96549920",
     "--runtime-init",
     "--nice-name=system_server",
     "com.android.server.SystemServer"
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index 1ff5665..ff110c8 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -33,6 +33,11 @@
 import android.database.Cursor;
 import android.graphics.drawable.AnimationDrawable;
 import android.graphics.drawable.Drawable;
+import android.location.Criteria;
+import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
+import android.location.LocationProvider;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.SystemClock;
@@ -44,6 +49,7 @@
 import android.text.TextWatcher;
 import android.util.AttributeSet;
 import android.util.Log;
+import android.view.ContextThemeWrapper;
 import android.view.Gravity;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
@@ -145,13 +151,22 @@
     private final WeakHashMap<String, Drawable> mOutsideDrawablesCache =
             new WeakHashMap<String, Drawable>();
     
+    // Objects we keep around for requesting location updates when the dialog is started
+    // (and canceling them when the dialog is stopped). We don't actually make use of the
+    // updates ourselves here, so the LocationListener is just a dummy which doesn't do
+    // anything. We only do this here so that other suggest providers which wish to provide
+    // location-based suggestions are more likely to get a good fresh location.
+    private LocationManager mLocationManager;
+    private LocationProvider mLocationProvider;
+    private LocationListener mDummyLocationListener;
+    
     /**
      * Constructor - fires it up and makes it look like the search UI.
      * 
      * @param context Application Context we can use for system acess
      */
     public SearchDialog(Context context) {
-        super(context, com.android.internal.R.style.Theme_SearchBar);
+        super(context, com.android.internal.R.style.Theme_GlobalSearchBar);
     }
 
     /**
@@ -221,6 +236,37 @@
                 RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH);
         
         mVoiceAppSearchIntent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);
+        
+        mLocationManager =
+                (LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE);
+        
+        if (mLocationManager != null) {
+            Criteria criteria = new Criteria();
+            criteria.setAccuracy(Criteria.ACCURACY_COARSE);
+    
+            String providerName = mLocationManager.getBestProvider(criteria, true);
+    
+            if (providerName != null) {
+                mLocationProvider = mLocationManager.getProvider(providerName);
+            }
+            
+            // Just a dumb listener that doesn't do anything - requesting location updates here
+            // is only intended to give location-based suggestion providers the best chance
+            // of getting a good fresh location.
+            mDummyLocationListener = new LocationListener() {
+                public void onLocationChanged(Location location) {                    
+                }
+
+                public void onProviderDisabled(String provider) {
+                }
+
+                public void onProviderEnabled(String provider) {
+                }
+
+                public void onStatusChanged(String provider, int status, Bundle extras) {
+                }
+            };
+        }
     }
 
     /**
@@ -348,6 +394,21 @@
                 getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
                         inputManager.showSoftInputUnchecked(0, null);
             }
+            
+            // The Dialog uses a ContextThemeWrapper for the context; use this to change the
+            // theme out from underneath us, between the global search theme and the in-app
+            // search theme. They are identical except that the global search theme does not
+            // dim the background of the window (because global search is full screen so it's
+            // not needed and this should save a little bit of time on global search invocation).
+            Object context = getContext();
+            if (context instanceof ContextThemeWrapper) {
+                ContextThemeWrapper wrapper = (ContextThemeWrapper) context;
+                if (globalSearch) {
+                    wrapper.setTheme(com.android.internal.R.style.Theme_GlobalSearchBar);
+                } else {
+                    wrapper.setTheme(com.android.internal.R.style.Theme_SearchBar);
+                }
+            }
             show();
         }
 
@@ -363,6 +424,8 @@
         // receive broadcasts
         getContext().registerReceiver(mBroadcastReceiver, mCloseDialogsFilter);
         getContext().registerReceiver(mBroadcastReceiver, mPackageFilter);
+        
+        startLocationUpdates();
     }
 
     /**
@@ -375,6 +438,8 @@
     public void onStop() {
         super.onStop();
         
+        stopLocationUpdates();
+        
         // TODO: Removing the listeners means that they never get called, since 
         // Dialog.dismissDialog() calls onStop() before sendDismissMessage().
         setOnCancelListener(null);
@@ -399,6 +464,25 @@
     }
     
     /**
+     * Asks the LocationManager for location updates so that it goes and gets a fresh location
+     * if needed.
+     */
+    private void startLocationUpdates() {
+        if (mLocationManager != null && mLocationProvider != null) {
+            mLocationManager.requestLocationUpdates(mLocationProvider.getName(),
+                    0, 0, mDummyLocationListener, getContext().getMainLooper());
+        }
+
+    }
+    
+    /**
+     * Makes sure to stop listening for location updates to save battery.
+     */
+    private void stopLocationUpdates() {
+        mLocationManager.removeUpdates(mDummyLocationListener);
+    }
+    
+    /**
      * Sets the search dialog to the 'working' state, which shows a working spinner in the
      * right hand size of the text field.
      * 
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index c204dda..bb25b68 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -151,9 +151,23 @@
             return ContentProvider.this.bulkInsert(uri, initialValues);
         }
 
-        public Uri[] bulkInsertEntities(Uri uri, Entity[] entities) {
+        public Uri insertEntity(Uri uri, Entity entities) {
             checkWritePermission(uri);
-            return ContentProvider.this.bulkInsertEntities(uri, entities);
+            return ContentProvider.this.insertEntity(uri, entities);
+        }
+
+        public ContentProviderResult[] applyBatch(ContentProviderOperation[] operations)
+                throws OperationApplicationException {
+            for (ContentProviderOperation operation : operations) {
+                if (operation.isReadOperation()) {
+                    checkReadPermission(operation.getUri());
+                }
+
+                if (operation.isWriteOperation()) {
+                    checkWritePermission(operation.getUri());
+                }
+            }
+            return ContentProvider.this.applyBatch(operations);
         }
 
         public int delete(Uri uri, String selection, String[] selectionArgs) {
@@ -167,9 +181,9 @@
             return ContentProvider.this.update(uri, values, selection, selectionArgs);
         }
 
-        public int[] bulkUpdateEntities(Uri uri, Entity[] entities) {
+        public int updateEntity(Uri uri, Entity entity) {
             checkWritePermission(uri);
-            return ContentProvider.this.bulkUpdateEntities(uri, entities);
+            return ContentProvider.this.updateEntity(uri, entity);
         }
 
         public ParcelFileDescriptor openFile(Uri uri, String mode)
@@ -403,14 +417,6 @@
         throw new UnsupportedOperationException();
     }
 
-    public Uri[] bulkInsertEntities(Uri uri, Entity[] entities) {
-        Uri[] result = new Uri[entities.length];
-        for (int i = 0; i < entities.length; i++) {
-            result[i] = insertEntity(uri, entities[i]);
-        }
-        return result;
-    }
-
     /**
      * A request to delete one or more rows. The selection clause is applied when performing
      * the deletion, allowing the operation to affect multiple rows in a
@@ -459,14 +465,6 @@
         throw new UnsupportedOperationException();
     }
 
-    public int[] bulkUpdateEntities(Uri uri, Entity[] entities) {
-        int[] result = new int[entities.length];
-        for (int i = 0; i < entities.length; i++) {
-            result[i] = updateEntity(uri, entities[i]);
-        }
-        return result;
-    }
-
     /**
      * Open a file blob associated with a content URI.
      * This method can be called from multiple
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index ed3ed42..08d4fca 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -96,22 +96,18 @@
 
     /** see {@link ContentProvider#insertEntity} */
     public Uri insertEntity(Uri uri, Entity entity) throws RemoteException {
-        return mContentProvider.bulkInsertEntities(uri, new Entity[]{entity})[0];
-    }
-
-    /** see {@link ContentProvider#bulkInsertEntities} */
-    public Uri[] bulkInsertEntities(Uri uri, Entity[] entities) throws RemoteException {
-        return mContentProvider.bulkInsertEntities(uri, entities);
+        return mContentProvider.insertEntity(uri, entity);
     }
 
     /** see {@link ContentProvider#updateEntity} */
     public int updateEntity(Uri uri, Entity entity) throws RemoteException {
-        return mContentProvider.bulkUpdateEntities(uri, new Entity[]{entity})[0];
+        return mContentProvider.updateEntity(uri, entity);
     }
 
-    /** see {@link ContentProvider#bulkUpdateEntities} */
-    public int[] bulkUpdateEntities(Uri uri, Entity[] entities) throws RemoteException {
-        return mContentProvider.bulkUpdateEntities(uri, entities);
+    /** see {@link ContentProvider#applyBatch} */
+    public ContentProviderResult[] applyBatch(ContentProviderOperation[] operations)
+            throws RemoteException, OperationApplicationException {
+        return mContentProvider.applyBatch(operations);
     }
 
     /**
diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java
index ac67076..4747726 100644
--- a/core/java/android/content/ContentProviderNative.java
+++ b/core/java/android/content/ContentProviderNative.java
@@ -154,37 +154,36 @@
                     return true;
                 }
 
-                case BULK_INSERT_ENTITIES_TRANSACTION:
+                case INSERT_ENTITIES_TRANSACTION:
                 {
                     data.enforceInterface(IContentProvider.descriptor);
                     Uri uri = Uri.CREATOR.createFromParcel(data);
-                    String className = data.readString();
-                    Class entityClass = Class.forName(className);
-                    int numEntities = data.readInt();
-                    Entity[] entities = new Entity[numEntities];
-                    for (int i = 0; i < numEntities; i++) {
-                        entities[i] = (Entity) data.readParcelable(entityClass.getClassLoader());
-                    }
-                    Uri[] uris = bulkInsertEntities(uri, entities);
+                    Entity entity = (Entity) data.readParcelable(null);
+                    Uri newUri = insertEntity(uri, entity);
                     reply.writeNoException();
-                    reply.writeTypedArray(uris, 0);
+                    Uri.writeToParcel(reply, newUri);
                     return true;
                 }
 
-                case BULK_UPDATE_ENTITIES_TRANSACTION:
+                case UPDATE_ENTITIES_TRANSACTION:
                 {
                     data.enforceInterface(IContentProvider.descriptor);
                     Uri uri = Uri.CREATOR.createFromParcel(data);
-                    String className = data.readString();
-                    Class entityClass = Class.forName(className);
-                    int numEntities = data.readInt();
-                    Entity[] entities = new Entity[numEntities];
-                    for (int i = 0; i < numEntities; i++) {
-                        entities[i] = (Entity) data.readParcelable(entityClass.getClassLoader());
-                    }
-                    int[] counts = bulkUpdateEntities(uri, entities);
+                    Entity entity = (Entity) data.readParcelable(null);
+                    int count = updateEntity(uri, entity);
                     reply.writeNoException();
-                    reply.writeIntArray(counts);
+                    reply.writeInt(count);
+                    return true;
+                }
+
+                case APPLY_BATCH_TRANSACTION:
+                {
+                    data.enforceInterface(IContentProvider.descriptor);
+                    final ContentProviderOperation[] operations =
+                            data.createTypedArray(ContentProviderOperation.CREATOR);
+                    final ContentProviderResult[] results = applyBatch(operations);
+                    reply.writeNoException();
+                    reply.writeTypedArray(results, 0);
                     return true;
                 }
 
@@ -472,23 +471,18 @@
         return count;
     }
 
-    public Uri[] bulkInsertEntities(Uri uri, Entity[] entities) throws RemoteException {
+    public ContentProviderResult[] applyBatch(ContentProviderOperation[] operations)
+            throws RemoteException, OperationApplicationException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
 
         data.writeInterfaceToken(IContentProvider.descriptor);
-        uri.writeToParcel(data, 0);
-        data.writeString(entities[0].getClass().getName());
-        data.writeInt(entities.length);
-        for (Entity entity : entities) {
-            data.writeParcelable(entity, 0);
-        }
+        data.writeTypedArray(operations, 0);
+        mRemote.transact(IContentProvider.APPLY_BATCH_TRANSACTION, data, reply, 0);
 
-        mRemote.transact(IContentProvider.BULK_INSERT_ENTITIES_TRANSACTION, data, reply, 0);
-
-        DatabaseUtils.readExceptionFromParcel(reply);
-        Uri[] results = new Uri[entities.length];
-        reply.readTypedArray(results, Uri.CREATOR);
+        DatabaseUtils.readExceptionWithOperationApplicationExceptionFromParcel(reply);
+        final ContentProviderResult[] results =
+                reply.createTypedArray(ContentProviderResult.CREATOR);
 
         data.recycle();
         reply.recycle();
@@ -496,28 +490,42 @@
         return results;
     }
 
-    public int[] bulkUpdateEntities(Uri uri, Entity[] entities) throws RemoteException {
+    public Uri insertEntity(Uri uri, Entity entity) throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
 
-        data.writeInterfaceToken(IContentProvider.descriptor);
-        uri.writeToParcel(data, 0);
-        data.writeString(entities[0].getClass().getName());
-        data.writeInt(entities.length);
-        for (Entity entity : entities) {
+        try {
+            data.writeInterfaceToken(IContentProvider.descriptor);
+            uri.writeToParcel(data, 0);
             data.writeParcelable(entity, 0);
+
+            mRemote.transact(IContentProvider.INSERT_ENTITIES_TRANSACTION, data, reply, 0);
+
+            DatabaseUtils.readExceptionFromParcel(reply);
+            return Uri.CREATOR.createFromParcel(reply);
+        } finally {
+            data.recycle();
+            reply.recycle();
         }
+    }
 
-        mRemote.transact(IContentProvider.BULK_UPDATE_ENTITIES_TRANSACTION, data, reply, 0);
+    public int updateEntity(Uri uri, Entity entity) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
 
-        DatabaseUtils.readExceptionFromParcel(reply);
-        int[] results = new int[entities.length];
-        reply.readIntArray(results);
+        try {
+            data.writeInterfaceToken(IContentProvider.descriptor);
+            uri.writeToParcel(data, 0);
+            data.writeParcelable(entity, 0);
 
-        data.recycle();
-        reply.recycle();
+            mRemote.transact(IContentProvider.UPDATE_ENTITIES_TRANSACTION, data, reply, 0);
 
-        return results;
+            DatabaseUtils.readExceptionFromParcel(reply);
+            return reply.readInt();
+        } finally {
+            data.recycle();
+            reply.recycle();
+        }
     }
 
     public int delete(Uri url, String selection, String[] selectionArgs)
diff --git a/core/java/android/content/ContentProviderOperation.java b/core/java/android/content/ContentProviderOperation.java
index 148cc35..ce92198 100644
--- a/core/java/android/content/ContentProviderOperation.java
+++ b/core/java/android/content/ContentProviderOperation.java
@@ -18,10 +18,15 @@
 
 import android.net.Uri;
 import android.database.Cursor;
+import android.os.Parcelable;
+import android.os.Parcel;
 
 import java.util.Map;
+import java.util.HashMap;
 
-public class ContentProviderOperation {
+import dalvik.system.VMStack;
+
+public class ContentProviderOperation implements Parcelable {
     private final static int TYPE_INSERT = 1;
     private final static int TYPE_UPDATE = 2;
     private final static int TYPE_DELETE = 3;
@@ -32,6 +37,7 @@
     private final String mSelection;
     private final String[] mSelectionArgs;
     private final ContentValues mValues;
+    private final Entity mEntity;
     private final Integer mExpectedCount;
     private final ContentValues mValuesBackReferences;
     private final Map<Integer, Integer> mSelectionArgsBackReferences;
@@ -46,6 +52,7 @@
         mType = builder.mType;
         mUri = builder.mUri;
         mValues = builder.mValues;
+        mEntity = builder.mEntity;
         mSelection = builder.mSelection;
         mSelectionArgs = builder.mSelectionArgs;
         mExpectedCount = builder.mExpectedCount;
@@ -53,6 +60,75 @@
         mValuesBackReferences = builder.mValuesBackReferences;
     }
 
+    private ContentProviderOperation(Parcel source, ClassLoader classLoader) {
+        mType = source.readInt();
+        mUri = Uri.CREATOR.createFromParcel(source);
+        mValues = source.readInt() != 0 ? ContentValues.CREATOR.createFromParcel(source) : null;
+        mEntity = (Entity) source.readParcelable(classLoader);
+        mSelection = source.readInt() != 0 ? source.readString() : null;
+        mSelectionArgs = source.readInt() != 0 ? source.readStringArray() : null;
+        mExpectedCount = source.readInt() != 0 ? source.readInt() : null;
+        mValuesBackReferences = source.readInt() != 0
+                
+                ? ContentValues.CREATOR.createFromParcel(source)
+                : null;
+        mSelectionArgsBackReferences = source.readInt() != 0
+                ? new HashMap<Integer, Integer>()
+                : null;
+        if (mSelectionArgsBackReferences != null) {
+            final int count = source.readInt();
+            for (int i = 0; i < count; i++) {
+                mSelectionArgsBackReferences.put(source.readInt(), source.readInt());
+            }
+        }
+    }
+
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mType);
+        Uri.writeToParcel(dest, mUri);
+        if (mValues != null) {
+            dest.writeInt(1);
+            mValues.writeToParcel(dest, 0);
+        } else {
+            dest.writeInt(0);
+        }
+        dest.writeParcelable(mEntity, 0);
+        if (mSelection != null) {
+            dest.writeInt(1);
+            dest.writeString(mSelection);
+        } else {
+            dest.writeInt(0);
+        }
+        if (mSelectionArgs != null) {
+            dest.writeInt(1);
+            dest.writeStringArray(mSelectionArgs);
+        } else {
+            dest.writeInt(0);
+        }
+        if (mExpectedCount != null) {
+            dest.writeInt(1);
+            dest.writeInt(mExpectedCount);
+        } else {
+            dest.writeInt(0);
+        }
+        if (mValuesBackReferences != null) {
+            dest.writeInt(1);
+            mValuesBackReferences.writeToParcel(dest, 0);
+        } else {
+            dest.writeInt(0);
+        }
+        if (mSelectionArgsBackReferences != null) {
+            dest.writeInt(1);
+            dest.writeInt(mSelectionArgsBackReferences.size());
+            for (Map.Entry<Integer, Integer> entry : mSelectionArgsBackReferences.entrySet()) {
+                dest.writeInt(entry.getKey());
+                dest.writeInt(entry.getValue());
+            }
+        } else {
+            dest.writeInt(0);
+        }
+    }
+
     /**
      * Create a {@link Builder} suitable for building an insert {@link ContentProviderOperation}.
      * @param uri The {@link Uri} that is the target of the insert.
@@ -92,6 +168,18 @@
         return new Builder(TYPE_COUNT, uri);
     }
 
+    public Uri getUri() {
+        return mUri;
+    }
+
+    public boolean isWriteOperation() {
+        return mType == TYPE_DELETE || mType == TYPE_INSERT || mType == TYPE_UPDATE;
+    }
+
+    public boolean isReadOperation() {
+        return mType == TYPE_COUNT;
+    }
+
     /**
      * Applies this operation using the given provider. The backRefs array is used to resolve any
      * back references that were requested using
@@ -113,7 +201,12 @@
                 resolveSelectionArgsBackReferences(backRefs, numBackRefs);
 
         if (mType == TYPE_INSERT) {
-            Uri newUri = provider.insert(mUri, values);
+            Uri newUri;
+            if (mEntity != null) {
+                newUri = provider.insertEntity(mUri, mEntity);
+            } else {
+                newUri = provider.insert(mUri, values);
+            }
             if (newUri == null) {
                 throw new OperationApplicationException("insert failed");
             }
@@ -124,7 +217,11 @@
         if (mType == TYPE_DELETE) {
             numRows = provider.delete(mUri, mSelection, selectionArgs);
         } else if (mType == TYPE_UPDATE) {
-            numRows = provider.update(mUri, values, mSelection, selectionArgs);
+            if (mEntity != null) {
+                numRows = provider.updateEntity(mUri, mEntity);
+            } else {
+                numRows = provider.update(mUri, values, mSelection, selectionArgs);
+            }
         } else if (mType == TYPE_COUNT) {
             Cursor cursor = provider.query(mUri, COUNT_COLUMNS, mSelection, selectionArgs, null);
             try {
@@ -239,6 +336,22 @@
         return backRefValue;
     }
 
+    public int describeContents() {
+        return 0;
+    }
+
+    public static final Creator<ContentProviderOperation> CREATOR =
+            new Creator<ContentProviderOperation>() {
+        public ContentProviderOperation createFromParcel(Parcel source) {
+            return new ContentProviderOperation(source, VMStack.getCallingClassLoader2());
+        }
+
+        public ContentProviderOperation[] newArray(int size) {
+            return new ContentProviderOperation[size];
+        }
+    };
+
+
     /**
      * Used to add parameters to a {@link ContentProviderOperation}. The {@link Builder} is
      * first created by calling {@link ContentProviderOperation#newInsert(android.net.Uri)},
@@ -255,6 +368,7 @@
         private String mSelection;
         private String[] mSelectionArgs;
         private ContentValues mValues;
+        private Entity mEntity;
         private Integer mExpectedCount;
         private ContentValues mValuesBackReferences;
         private Map<Integer, Integer> mSelectionArgsBackReferences;
@@ -268,8 +382,16 @@
             mUri = uri;
         }
 
-        /** Create a ContentroviderOperation from this {@link Builder}. */
+        /** Create a ContentProviderOperation from this {@link Builder}. */
         public ContentProviderOperation build() {
+            if (mValues != null && mEntity != null) {
+                throw new IllegalArgumentException("you are not allowed to specify both an entity "
+                        + "and a values");
+            }
+            if (mEntity != null && mValuesBackReferences != null) {
+                throw new IllegalArgumentException("you are not allowed to specify both an entity "
+                        + "and a values backreference");
+            }
             return new ContentProviderOperation(this);
         }
 
@@ -295,7 +417,7 @@
          * Add a {@link Map} of back references. The integer key is the index of the selection arg
          * to set and the integer value is the index of the previous result whose
          * value should be used for the arg. If any value at that index of the selection arg
-         * that was specified by {@likn withSelection} will be overwritten.
+         * that was specified by {@link #withSelection} will be overwritten.
          * This can only be used with builders of type update, delete, or count query.
          * @return this builder, to allow for chaining.
          */
@@ -323,6 +445,20 @@
         }
 
         /**
+         * The ContentValues to use. This may be null. These values may be overwritten by
+         * the corresponding value specified by {@link #withValueBackReferences(ContentValues)}.
+         * This can only be used with builders of type insert or update.
+         * @return this builder, to allow for chaining.
+         */
+        public Builder withEntity(Entity entity) {
+            if (mType != TYPE_INSERT && mType != TYPE_UPDATE) {
+                throw new IllegalArgumentException("only inserts and updates can have an entity");
+            }
+            mEntity = entity;
+            return this;
+        }
+
+        /**
          * The selection and arguments to use. An occurrence of '?' in the selection will be
          * replaced with the corresponding occurence of the selection argument. Any of the
          * selection arguments may be overwritten by a selection argument back reference as
diff --git a/core/java/android/content/ContentProviderResult.java b/core/java/android/content/ContentProviderResult.java
index 2e34e40..34aaa6d 100644
--- a/core/java/android/content/ContentProviderResult.java
+++ b/core/java/android/content/ContentProviderResult.java
@@ -17,12 +17,14 @@
 package android.content;
 
 import android.net.Uri;
+import android.os.Parcelable;
+import android.os.Parcel;
 
 /**
  * Contains the result of the application of a {@link ContentProviderOperation}. It is guaranteed
  * to have exactly one of {@link #uri} or {@link #count} set.
  */
-public class ContentProviderResult {
+public class ContentProviderResult implements Parcelable {
     public final Uri uri;
     public final Integer count;
 
@@ -36,4 +38,40 @@
         this.count = count;
         this.uri = null;
     }
+
+    public ContentProviderResult(Parcel source) {
+        int type = source.readInt();
+        if (type == 1) {
+            count = source.readInt();
+            uri = null;
+        } else {
+            count = null;
+            uri = Uri.CREATOR.createFromParcel(source);
+        }
+    }
+
+    public void writeToParcel(Parcel dest, int flags) {
+        if (uri == null) {
+            dest.writeInt(1);
+            dest.writeInt(count);
+        } else {
+            dest.writeInt(2);
+            uri.writeToParcel(dest, 0);
+        }
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public static final Creator<ContentProviderResult> CREATOR =
+            new Creator<ContentProviderResult>() {
+        public ContentProviderResult createFromParcel(Parcel source) {
+            return new ContentProviderResult(source);
+        }
+
+        public ContentProviderResult[] newArray(int size) {
+            return new ContentProviderResult[size];
+        }
+    };
 }
\ No newline at end of file
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index f9bed59..f7b52fa 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -166,35 +166,69 @@
         }
     }
 
-    class EntityIteratorWrapper implements EntityIterator {
+    /**
+     * EntityIterator wrapper that releases the associated ContentProviderClient when the
+     * iterator is closed.
+     */
+    private class EntityIteratorWrapper implements EntityIterator {
         private final EntityIterator mInner;
         private final ContentProviderClient mClient;
+        private volatile boolean mClientReleased;
 
         EntityIteratorWrapper(EntityIterator inner, ContentProviderClient client) {
             mInner = inner;
             mClient = client;
+            mClientReleased = false;
         }
 
         public boolean hasNext() throws RemoteException {
+            if (mClientReleased) {
+                throw new IllegalStateException("this iterator is already closed");
+            }
             return mInner.hasNext();
         }
 
         public Entity next() throws RemoteException {
+            if (mClientReleased) {
+                throw new IllegalStateException("this iterator is already closed");
+            }
             return mInner.next();
         }
 
         public void close() {
             mClient.release();
             mInner.close();
+            mClientReleased = true;
         }
 
         protected void finalize() throws Throwable {
-            close();
+            if (!mClientReleased) {
+                mClient.release();
+            }
             super.finalize();
         }
     }
 
-    public final EntityIterator queryEntity(Uri uri,
+    /**
+     * Query the given URI, returning an {@link EntityIterator} over the result set.
+     *
+     * @param uri The URI, using the content:// scheme, for the content to
+     *         retrieve.
+     * @param selection A filter declaring which rows to return, formatted as an
+     *         SQL WHERE clause (excluding the WHERE itself). Passing null will
+     *         return all rows for the given URI.
+     * @param selectionArgs You may include ?s in selection, which will be
+     *         replaced by the values from selectionArgs, in the order that they
+     *         appear in the selection. The values will be bound as Strings.
+     * @param sortOrder How to order the rows, formatted as an SQL ORDER BY
+     *         clause (excluding the ORDER BY itself). Passing null will use the
+     *         default sort order, which may be unordered.
+     * @return An EntityIterator object
+     * @throws RemoteException thrown if a RemoteException is encountered while attempting
+     *   to communicate with a remote provider.
+     * @throws IllegalArgumentException thrown if there is no provider that matches the uri
+     */
+    public final EntityIterator queryEntities(Uri uri,
             String selection, String[] selectionArgs, String sortOrder) throws RemoteException {
         ContentProviderClient provider = acquireContentProviderClient(uri);
         if (provider == null) {
@@ -532,6 +566,16 @@
         }
     }
 
+    /**
+     * Inserts an Entity at the given URL.
+     *
+     * @param uri The URL of the table to insert into.
+     * @param entity an Entity to insert at uri. This must be the same Entity subtype that the
+     *   matching content provider expects at that uri.
+     * @return the URL of the newly created row.
+     * @throws RemoteException thrown if a RemoteException is encountered while attempting
+     *   to communicate with a remote provider.
+     */
     public final Uri insertEntity(Uri uri, Entity entity) throws RemoteException {
         ContentProviderClient provider = acquireContentProviderClient(uri);
         if (provider == null) {
@@ -544,6 +588,16 @@
         }
     }
 
+    /**
+     * Replaces the Entity at the given URL with the provided entity.
+     *
+     * @param uri The URL of the entity to update.
+     * @param entity the new version of the entity
+     * @return the number of rows that are updated. Will be 0 if an entity no longer exists
+     * at uri otherwise it will be 1.
+     * @throws RemoteException thrown if a RemoteException is encountered while attempting
+     *   to communicate with a remote provider.
+     */
     public final int updateEntity(Uri uri, Entity entity) throws RemoteException {
         ContentProviderClient provider = acquireContentProviderClient(uri);
         if (provider == null) {
@@ -556,27 +610,31 @@
         }
     }
 
-    public final Uri[] bulkInsertEntities(Uri uri, Entity[] entities)
-            throws RemoteException {
-        ContentProviderClient provider = acquireContentProviderClient(uri);
+    /**
+     * Applies each of the {@link ContentProviderOperation} objects and returns an array
+     * of their results. Passes through OperationApplicationException, which may be thrown
+     * by the call to {@link ContentProviderOperation#apply}.
+     * If all the applications succeed then a {@link ContentProviderResult} array with the
+     * same number of elements as the operations will be returned. It is implementation-specific
+     * how many, if any, operations will have been successfully applied if a call to
+     * apply results in a {@link OperationApplicationException}.
+     * @param authority the authority of the ContentProvider to which this batch should be applied
+     * @param operations the operations to apply
+     * @return the results of the applications
+     * @throws OperationApplicationException thrown if an application fails.
+     * See {@link ContentProviderOperation#apply} for more information.
+     * @throws RemoteException thrown if a RemoteException is encountered while attempting
+     *   to communicate with a remote provider.
+     */
+    public ContentProviderResult[] applyBatch(String authority,
+            ContentProviderOperation[] operations)
+            throws RemoteException, OperationApplicationException {
+        ContentProviderClient provider = acquireContentProviderClient(authority);
         if (provider == null) {
-            throw new IllegalArgumentException("Unknown URL " + uri);
+            throw new IllegalArgumentException("Unknown authority " + authority);
         }
         try {
-            return provider.bulkInsertEntities(uri, entities);
-        } finally {
-            provider.release();
-        }
-    }
-
-    public final int[] bulkUpdateEntities(Uri uri, Entity[] entities)
-            throws RemoteException {
-        ContentProviderClient provider = acquireContentProviderClient(uri);
-        if (provider == null) {
-            throw new IllegalArgumentException("Unknown URL " + uri);
-        }
-        try {
-            return provider.bulkUpdateEntities(uri, entities);
+            return provider.applyBatch(operations);
         } finally {
             provider.release();
         }
diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java
index b4d1865..f82c982 100644
--- a/core/java/android/content/IContentProvider.java
+++ b/core/java/android/content/IContentProvider.java
@@ -50,16 +50,18 @@
     public Uri insert(Uri url, ContentValues initialValues)
             throws RemoteException;
     public int bulkInsert(Uri url, ContentValues[] initialValues) throws RemoteException;
-    public Uri[] bulkInsertEntities(Uri uri, Entity[] entities) throws RemoteException;
+    public Uri insertEntity(Uri uri, Entity entities) throws RemoteException;
     public int delete(Uri url, String selection, String[] selectionArgs)
             throws RemoteException;
     public int update(Uri url, ContentValues values, String selection,
             String[] selectionArgs) throws RemoteException;
-    public int[] bulkUpdateEntities(Uri uri, Entity[] entities) throws RemoteException;
+    public int updateEntity(Uri uri, Entity entity) throws RemoteException;
     public ParcelFileDescriptor openFile(Uri url, String mode)
             throws RemoteException, FileNotFoundException;
     public AssetFileDescriptor openAssetFile(Uri url, String mode)
             throws RemoteException, FileNotFoundException;
+    public ContentProviderResult[] applyBatch(ContentProviderOperation[] operations)
+            throws RemoteException, OperationApplicationException;
 
     /* IPC constants */
     static final String descriptor = "android.content.IContentProvider";
@@ -72,7 +74,8 @@
     static final int BULK_INSERT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 12;
     static final int OPEN_FILE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 13;
     static final int OPEN_ASSET_FILE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 14;
-    static final int BULK_INSERT_ENTITIES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 16;
-    static final int BULK_UPDATE_ENTITIES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 17;
+    static final int INSERT_ENTITIES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 16;
+    static final int UPDATE_ENTITIES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 17;
     static final int QUERY_ENTITIES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 18;
+    static final int APPLY_BATCH_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 19;
 }
diff --git a/core/java/android/content/IEntityIterator.java b/core/java/android/content/IEntityIterator.java
index eb800f7..1887df2 100644
--- a/core/java/android/content/IEntityIterator.java
+++ b/core/java/android/content/IEntityIterator.java
@@ -25,6 +25,7 @@
 
 /**
  * ICPC interface methods for an iterator over Entity objects.
+ * @hide
  */
 public interface IEntityIterator extends IInterface {
     /** Local-side IPC implementation stub class. */
@@ -92,7 +93,6 @@
                         return true;
                     }
                     reply.writeNoException();
-                    reply.writeString(entity.getClass().getName());
                     reply.writeParcelable(entity, 0);
                     return true;
                 }
@@ -145,22 +145,15 @@
             public Entity next() throws RemoteException {
                 Parcel _data = Parcel.obtain();
                 Parcel _reply = Parcel.obtain();
-                Entity _result;
                 try {
                     _data.writeInterfaceToken(DESCRIPTOR);
                     mRemote.transact(Stub.TRANSACTION_next, _data, _reply, 0);
                     _reply.readException();
-                    final String className = _reply.readString();
-                    final Class entityClass = Class.forName(className);
-                    ClassLoader classLoader = entityClass.getClassLoader();
-                    _result = (Entity) _reply.readParcelable(classLoader);
-                } catch (ClassNotFoundException e) {
-                   throw new RuntimeException(e);
+                    return (Entity) _reply.readParcelable(null /* classLoader */);
                 } finally {
                     _reply.recycle();
                     _data.recycle();
                 }
-                return _result;
             }
 
             public void close() throws RemoteException {
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index fcff1a8..147968b 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -398,6 +398,15 @@
     public static final int INSTALL_FAILED_TEST_ONLY = -15;
 
     /**
+     * Installation return code: this is passed to the {@link IPackageInstallObserver} by
+     * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
+     * the package being installed contains native code, but none that is
+     * compatible with the the device's CPU_ABI.
+     * @hide
+     */
+    public static final int INSTALL_FAILED_CPU_ABI_INCOMPATIBLE = -16;
+
+    /**
      * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
      * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
      * if the parser was given a path that is not a file, or does not end with the expected
diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java
index 78ef374..4ca6601 100644
--- a/core/java/android/database/DatabaseUtils.java
+++ b/core/java/android/database/DatabaseUtils.java
@@ -20,6 +20,7 @@
 
 import android.content.ContentValues;
 import android.content.Context;
+import android.content.OperationApplicationException;
 import android.database.sqlite.SQLiteAbortException;
 import android.database.sqlite.SQLiteConstraintException;
 import android.database.sqlite.SQLiteDatabase;
@@ -82,6 +83,8 @@
             code = 8;
         } else if (e instanceof SQLiteException) {
             code = 9;
+        } else if (e instanceof OperationApplicationException) {
+            code = 10;
         } else {
             reply.writeException(e);
             Log.e(TAG, "Writing exception to parcel", e);
@@ -123,6 +126,18 @@
         }
     }
 
+    public static void readExceptionWithOperationApplicationExceptionFromParcel(
+            Parcel reply) throws OperationApplicationException {
+        int code = reply.readInt();
+        if (code == 0) return;
+        String msg = reply.readString();
+        if (code == 10) {
+            throw new OperationApplicationException(msg);
+        } else {
+            DatabaseUtils.readExceptionFromParcel(reply, msg, code);
+        }
+    }
+
     private static final void readExceptionFromParcel(Parcel reply, String msg, int code) {
         switch (code) {
             case 2:
diff --git a/tests/sketch/src/com/android/gesture/Gesture.java b/core/java/android/gesture/Gesture.java
similarity index 61%
rename from tests/sketch/src/com/android/gesture/Gesture.java
rename to core/java/android/gesture/Gesture.java
index 44711ca..6aca105 100755
--- a/tests/sketch/src/com/android/gesture/Gesture.java
+++ b/core/java/android/gesture/Gesture.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.gesture;
+package android.gesture;
 
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
@@ -23,10 +23,13 @@
 import android.graphics.RectF;
 import android.os.Parcel;
 import android.os.Parcelable;
-
-import org.xmlpull.v1.XmlSerializer;
+import android.util.Log;
 
 import java.io.IOException;
+import java.io.DataOutputStream;
+import java.io.DataInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ByteArrayInputStream;
 import java.util.ArrayList;
 
 /**
@@ -54,6 +57,11 @@
         mGestureID = GESTURE_ID_BASE + sGestureCount++;
     }
 
+    void recycle() {
+        mStrokes.clear();
+        mBoundingBox.setEmpty();
+    }
+
     /**
      * @return all the strokes of the gesture
      */
@@ -108,6 +116,40 @@
         return mBoundingBox;
     }
 
+    public Path toPath() {
+        return toPath(null);
+    }
+
+    public Path toPath(Path path) {
+        if (path == null) path = new Path();
+
+        final ArrayList<GestureStroke> strokes = mStrokes;
+        final int count = strokes.size();
+
+        for (int i = 0; i < count; i++) {
+            path.addPath(strokes.get(i).getPath());
+        }
+
+        return path;
+    }
+
+    public Path toPath(int width, int height, int edge, int numSample) {
+        return toPath(null, width, height, edge, numSample);
+    }
+
+    public Path toPath(Path path, int width, int height, int edge, int numSample) {
+        if (path == null) path = new Path();
+
+        final ArrayList<GestureStroke> strokes = mStrokes;
+        final int count = strokes.size();
+
+        for (int i = 0; i < count; i++) {
+            path.addPath(strokes.get(i).toPath(width - 2 * edge, height - 2 * edge, numSample));
+        }
+
+        return path;
+    }
+
     /**
      * Set the id of the gesture
      * 
@@ -149,10 +191,12 @@
      * @return the bitmap
      */
     public Bitmap toBitmap(int width, int height, int edge, int numSample, int color) {
-        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
-        Canvas canvas = new Canvas(bitmap);
+        final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+        final Canvas canvas = new Canvas(bitmap);
+
         canvas.translate(edge, edge);
-        Paint paint = new Paint();
+
+        final Paint paint = new Paint();
         paint.setAntiAlias(BITMAP_RENDERING_ANTIALIAS);
         paint.setDither(BITMAP_RENDERING_DITHER);
         paint.setColor(color);
@@ -182,10 +226,12 @@
      * @return the bitmap
      */
     public Bitmap toBitmap(int width, int height, int edge, int color) {
-        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
-        Canvas canvas = new Canvas(bitmap);
+        final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+        final Canvas canvas = new Canvas(bitmap);
+
         canvas.translate(edge, edge);
-        Paint paint = new Paint();
+
+        final Paint paint = new Paint();
         paint.setAntiAlias(BITMAP_RENDERING_ANTIALIAS);
         paint.setDither(BITMAP_RENDERING_DITHER);
         paint.setColor(color);
@@ -193,78 +239,66 @@
         paint.setStrokeJoin(Paint.Join.ROUND);
         paint.setStrokeCap(Paint.Cap.ROUND);
         paint.setStrokeWidth(BITMAP_RENDERING_WIDTH);
-        ArrayList<GestureStroke> strokes = mStrokes;
-        int count = strokes.size();
+
+        final ArrayList<GestureStroke> strokes = mStrokes;
+        final int count = strokes.size();
+
         for (int i = 0; i < count; i++) {
-            GestureStroke stroke = strokes.get(i);
-            stroke.draw(canvas, paint);
+            strokes.get(i).draw(canvas, paint);
         }
 
         return bitmap;
     }
 
-    /**
-     * Save the gesture as XML
-     * 
-     * @param namespace
-     * @param serializer
-     * @throws IOException
-     */
-    void toXML(String namespace, XmlSerializer serializer) throws IOException {
-        serializer.startTag(namespace, GestureConstants.XML_TAG_GESTURE);
-        serializer.attribute(namespace, GestureConstants.XML_TAG_ID, Long.toString(mGestureID));
-        ArrayList<GestureStroke> strokes = mStrokes;
-        int count = strokes.size();
-        for (int i = 0; i < count; i++) {
-            GestureStroke stroke = strokes.get(i);
-            stroke.toXML(namespace, serializer);
-        }
-        serializer.endTag(namespace, GestureConstants.XML_TAG_GESTURE);
-    }
+    void serialize(DataOutputStream out) throws IOException {
+        final ArrayList<GestureStroke> strokes = mStrokes;
+        final int count = strokes.size();
 
-    /**
-     * Create the gesture from a string
-     * 
-     * @param str
-     */
-    public void createFromString(String str) {
-        int startIndex = 0;
-        int endIndex;
-        while ((endIndex =
-                str.indexOf(GestureConstants.STRING_GESTURE_DELIIMITER, startIndex + 1)) != -1) {
-            String token = str.substring(startIndex, endIndex);
-            if (startIndex > 0) { // stroke tokens
-                addStroke(GestureStroke.createFromString(token));
-            } else { // id token
-                mGestureID = Long.parseLong(token);
-            }
-            startIndex = endIndex + 1;
+        // Write gesture ID
+        out.writeLong(mGestureID);
+        // Write number of strokes
+        out.writeInt(count);
+
+        for (int i = 0; i < count; i++) {
+            strokes.get(i).serialize(out);
         }
     }
 
-    /**
-     * Convert the gesture to string
-     */
-    @Override
-    public String toString() {
-        StringBuilder str = new StringBuilder();
-        str.append(mGestureID);
-        ArrayList<GestureStroke> strokes = mStrokes;
-        int count = strokes.size();
+    static Gesture deserialize(DataInputStream in) throws IOException {
+        final Gesture gesture = new Gesture();
+
+        // Gesture ID
+        gesture.mGestureID = in.readLong();
+        // Number of strokes
+        final int count = in.readInt();
+
         for (int i = 0; i < count; i++) {
-            GestureStroke stroke = strokes.get(i);
-            str.append(GestureConstants.STRING_GESTURE_DELIIMITER);
-            str.append(stroke.toString());
+            gesture.addStroke(GestureStroke.deserialize(in));
         }
 
-        return str.toString();
+        return gesture;
     }
 
     public static final Parcelable.Creator<Gesture> CREATOR = new Parcelable.Creator<Gesture>() {
         public Gesture createFromParcel(Parcel in) {
-            String str = in.readString();
-            Gesture gesture = new Gesture();
-            gesture.createFromString(str);
+            Gesture gesture = null;
+            final long gestureID = in.readLong();
+
+            final DataInputStream inStream = new DataInputStream(
+                    new ByteArrayInputStream(in.createByteArray()));
+
+            try {
+                gesture = deserialize(inStream);
+            } catch (IOException e) {
+                Log.e(GestureConstants.LOG_TAG, "Error reading Gesture from parcel:", e);
+            } finally {
+                GestureUtilities.closeStream(inStream);
+            }
+
+            if (gesture != null) {
+                gesture.mGestureID = gestureID;
+            }
+
             return gesture;
         }
 
@@ -273,35 +307,31 @@
         }
     };
 
-    /**
-     * Build a gesture from a byte array
-     * 
-     * @param bytes
-     * @return the gesture
-     */
-    static Gesture buildFromArray(byte[] bytes) {
-        String str = new String(bytes);
-        Gesture gesture = new Gesture();
-        gesture.createFromString(str);
-        return gesture;
-    }
-
-    /**
-     * Save a gesture to a byte array
-     * 
-     * @param stroke
-     * @return the byte array
-     */
-    static byte[] saveToArray(Gesture stroke) {
-        String str = stroke.toString();
-        return str.getBytes();
-    }
-
     public void writeToParcel(Parcel out, int flags) {
-        out.writeString(toString());
+        out.writeLong(mGestureID);
+
+        boolean result = false;
+        final ByteArrayOutputStream byteStream =
+                new ByteArrayOutputStream(GestureConstants.IO_BUFFER_SIZE);
+        final DataOutputStream outStream = new DataOutputStream(byteStream);
+
+        try {
+            serialize(outStream);
+            result = true;
+        } catch (IOException e) {
+            Log.e(GestureConstants.LOG_TAG, "Error writing Gesture to parcel:", e);
+        } finally {
+            GestureUtilities.closeStream(outStream);
+            GestureUtilities.closeStream(byteStream);
+        }
+
+        if (result) {
+            out.writeByteArray(byteStream.toByteArray());
+        }
     }
 
     public int describeContents() {
-        return CONTENTS_FILE_DESCRIPTOR;
+        return 0;
     }
 }
+
diff --git a/tests/sketch/src/com/android/gesture/GestureActionListener.java b/core/java/android/gesture/GestureConstants.java
similarity index 62%
copy from tests/sketch/src/com/android/gesture/GestureActionListener.java
copy to core/java/android/gesture/GestureConstants.java
index c9c5232..230db0c 100644
--- a/tests/sketch/src/com/android/gesture/GestureActionListener.java
+++ b/core/java/android/gesture/GestureConstants.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2009 The Android Open Source Project
+ * Copyright (C) 2009 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,8 +14,13 @@
  * limitations under the License.
  */
 
-package com.android.gesture;
+package android.gesture;
 
-public interface GestureActionListener {
-    public void onGesturePerformed(GestureOverlay overlay, Gesture gesture);
+interface GestureConstants {
+    static final int STROKE_STRING_BUFFER_SIZE = 1024;
+    static final int STROKE_POINT_BUFFER_SIZE = 100; // number of points
+
+    static final int IO_BUFFER_SIZE = 32 * 1024; // 32K
+
+    static final String LOG_TAG = "Gestures";
 }
diff --git a/core/java/android/gesture/GestureLibrary.java b/core/java/android/gesture/GestureLibrary.java
new file mode 100644
index 0000000..1cf192e
--- /dev/null
+++ b/core/java/android/gesture/GestureLibrary.java
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2008-2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.gesture;
+
+import android.util.Log;
+import android.os.SystemClock;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.DataOutputStream;
+import java.io.DataInputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Set;
+import java.util.Map;
+
+import static android.gesture.GestureConstants.LOG_TAG;
+
+/**
+ * GestureLibrary maintains gesture examples and makes predictions on a new
+ * gesture
+ */
+//
+//    File format for GestureLibrary:
+//
+//                Nb. bytes   Java type   Description
+//                -----------------------------------
+//    Header
+//                2 bytes     short       File format version number
+//                4 bytes     int         Number of entries
+//    Entry
+//                X bytes     UTF String  Entry name
+//                4 bytes     int         Number of gestures
+//    Gesture
+//                8 bytes     long        Gesture ID
+//                4 bytes     int         Number of strokes
+//    Stroke
+//                4 bytes     int         Number of points
+//    Point
+//                4 bytes     float       X coordinate of the point
+//                4 bytes     float       Y coordinate of the point
+//                8 bytes     long        Time stamp
+//
+public class GestureLibrary {
+    public static final int SEQUENCE_INVARIANT = 1;
+    // when SEQUENCE_SENSITIVE is used, only single stroke gestures are currently allowed
+    public static final int SEQUENCE_SENSITIVE = 2;
+
+    // ORIENTATION_SENSITIVE and ORIENTATION_INVARIANT are only for SEQUENCE_SENSITIVE gestures
+    public static final int ORIENTATION_INVARIANT = 1;
+    public static final int ORIENTATION_SENSITIVE = 2;
+
+    private static final short FILE_FORMAT_VERSION = 1;
+
+    private static final boolean PROFILE_LOADING_SAVING = false;
+
+    private int mSequenceType = SEQUENCE_SENSITIVE;
+    private int mOrientationStyle = ORIENTATION_SENSITIVE;
+
+    private final String mGestureFileName;
+
+    private final HashMap<String, ArrayList<Gesture>> mNamedGestures =
+            new HashMap<String, ArrayList<Gesture>>();
+
+    private Learner mClassifier;
+
+    private boolean mChanged = false;
+
+    /**
+     * @param path where gesture data is stored
+     */
+    public GestureLibrary(String path) {
+        mGestureFileName = path;
+        mClassifier = new InstanceLearner();
+    }
+
+    /**
+     * Specify how the gesture library will handle orientation. 
+     * Use ORIENTATION_INVARIANT or ORIENTATION_SENSITIVE
+     * 
+     * @param style
+     */
+    public void setOrientationStyle(int style) {
+        mOrientationStyle = style;
+    }
+
+    public int getOrientationStyle() {
+        return mOrientationStyle;
+    }
+
+    /**
+     * @param type SEQUENCE_INVARIANT or SEQUENCE_SENSITIVE
+     */
+    public void setSequenceType(int type) {
+        mSequenceType = type;
+    }
+
+    /**
+     * @return SEQUENCE_INVARIANT or SEQUENCE_SENSITIVE
+     */
+    public int getSequenceType() {
+        return mSequenceType;
+    }
+
+    /**
+     * Get all the gesture entry names in the library
+     * 
+     * @return a set of strings
+     */
+    public Set<String> getGestureEntries() {
+        return mNamedGestures.keySet();
+    }
+
+    /**
+     * Recognize a gesture
+     * 
+     * @param gesture the query
+     * @return a list of predictions of possible entries for a given gesture
+     */
+    public ArrayList<Prediction> recognize(Gesture gesture) {
+        Instance instance = Instance.createInstance(mSequenceType, gesture, null);
+        return mClassifier.classify(mSequenceType, instance.vector);
+    }
+
+    /**
+     * Add a gesture for the entry
+     * 
+     * @param entryName entry name
+     * @param gesture
+     */
+    public void addGesture(String entryName, Gesture gesture) {
+        if (entryName == null || entryName.length() == 0) {
+            return;
+        }
+        ArrayList<Gesture> gestures = mNamedGestures.get(entryName);
+        if (gestures == null) {
+            gestures = new ArrayList<Gesture>();
+            mNamedGestures.put(entryName, gestures);
+        }
+        gestures.add(gesture);
+        mClassifier.addInstance(Instance.createInstance(mSequenceType, gesture, entryName));
+        mChanged = true;
+    }
+
+    /**
+     * Remove a gesture from the library. If there are no more gestures for the
+     * given entry, the gesture entry will be removed.
+     * 
+     * @param entryName entry name
+     * @param gesture
+     */
+    public void removeGesture(String entryName, Gesture gesture) {
+        ArrayList<Gesture> gestures = mNamedGestures.get(entryName);
+        if (gestures == null) {
+            return;
+        }
+
+        gestures.remove(gesture);
+
+        // if there are no more samples, remove the entry automatically
+        if (gestures.isEmpty()) {
+            mNamedGestures.remove(entryName);
+        }
+
+        mClassifier.removeInstance(gesture.getID());
+
+        mChanged = true;
+    }
+
+    /**
+     * Remove a entry of gestures
+     * 
+     * @param entryName the entry name
+     */
+    public void removeEntry(String entryName) {
+        mNamedGestures.remove(entryName);
+        mClassifier.removeInstances(entryName);
+        mChanged = true;
+    }
+
+    /**
+     * Get all the gestures of an entry
+     * 
+     * @param entryName
+     * @return the list of gestures that is under this name
+     */
+    public ArrayList<Gesture> getGestures(String entryName) {
+        ArrayList<Gesture> gestures = mNamedGestures.get(entryName);
+        if (gestures != null) {
+            return new ArrayList<Gesture>(gestures);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Save the gesture library
+     */
+    public boolean save() {
+        if (!mChanged) {
+            return true;
+        }
+
+        boolean result = false;
+        DataOutputStream out = null;
+
+        try {
+            File file = new File(mGestureFileName);
+            if (!file.getParentFile().exists()) {
+                if (!file.getParentFile().mkdirs()) {
+                    return false;
+                }
+            }
+
+            long start;
+            if (PROFILE_LOADING_SAVING) {
+                start = SystemClock.elapsedRealtime();
+            }
+
+            final HashMap<String, ArrayList<Gesture>> maps = mNamedGestures;
+
+            out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file),
+                    GestureConstants.IO_BUFFER_SIZE));
+            // Write version number
+            out.writeShort(FILE_FORMAT_VERSION);
+            // Write number of entries
+            out.writeInt(maps.size());
+
+            for (Map.Entry<String, ArrayList<Gesture>> entry : maps.entrySet()) {
+                final String key = entry.getKey();
+                final ArrayList<Gesture> examples = entry.getValue();
+                final int count = examples.size();
+
+                // Write entry name
+                out.writeUTF(key);
+                // Write number of examples for this entry
+                out.writeInt(count);
+
+                for (int i = 0; i < count; i++) {
+                    examples.get(i).serialize(out);
+                }
+            }
+
+            out.flush();
+
+            if (PROFILE_LOADING_SAVING) {
+                long end = SystemClock.elapsedRealtime();
+                Log.d(LOG_TAG, "Saving gestures library = " + (end - start) + " ms");
+            }
+
+            mChanged = false;
+            result = true;
+        } catch (IOException ex) {
+            Log.d(LOG_TAG, "Failed to save gestures:", ex);
+        } finally {
+            GestureUtilities.closeStream(out);
+        }
+
+        return result;
+    }
+
+    /**
+     * Load the gesture library
+     */
+    public boolean load() {
+        boolean result = false;
+
+        final File file = new File(mGestureFileName);
+        if (file.exists()) {
+            DataInputStream in = null;
+            try {
+                in = new DataInputStream(new BufferedInputStream(
+                        new FileInputStream(mGestureFileName), GestureConstants.IO_BUFFER_SIZE));
+
+                long start;
+                if (PROFILE_LOADING_SAVING) {
+                    start = SystemClock.elapsedRealtime();
+                }
+
+                // Read file format version number
+                final short versionNumber = in.readShort();
+                switch (versionNumber) {
+                    case 1:
+                        readFormatV1(in);
+                        break;
+                }
+
+                if (PROFILE_LOADING_SAVING) {
+                    long end = SystemClock.elapsedRealtime();
+                    Log.d(LOG_TAG, "Loading gestures library = " + (end - start) + " ms");
+                }
+
+                result = true;
+            } catch (IOException ex) {
+                Log.d(LOG_TAG, "Failed to load gestures:", ex);
+            } finally {
+                GestureUtilities.closeStream(in);
+            }
+        }
+
+        return result;
+    }
+
+    private void readFormatV1(DataInputStream in) throws IOException {
+        final Learner classifier = mClassifier;
+        final HashMap<String, ArrayList<Gesture>> namedGestures = mNamedGestures;
+        namedGestures.clear();
+
+        // Number of entries in the library
+        final int entriesCount = in.readInt();
+
+        for (int i = 0; i < entriesCount; i++) {
+            // Entry name
+            final String name = in.readUTF();
+            // Number of gestures
+            final int gestureCount = in.readInt();
+
+            final ArrayList<Gesture> gestures = new ArrayList<Gesture>(gestureCount);
+            for (int j = 0; j < gestureCount; j++) {
+                final Gesture gesture = Gesture.deserialize(in);
+                gestures.add(gesture);
+                classifier.addInstance(Instance.createInstance(mSequenceType, gesture, name));
+            }
+
+            namedGestures.put(name, gestures);
+        }
+    }
+}
diff --git a/core/java/android/gesture/GestureOverlayView.java b/core/java/android/gesture/GestureOverlayView.java
new file mode 100755
index 0000000..c21cc55
--- /dev/null
+++ b/core/java/android/gesture/GestureOverlayView.java
@@ -0,0 +1,688 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.gesture;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.animation.AnimationUtils;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.widget.FrameLayout;
+import android.os.SystemClock;
+import com.android.internal.R;
+
+import java.util.ArrayList;
+
+/**
+ * A transparent overlay for gesture input that can be placed on top of other
+ * widgets or contain other widgets.
+ *
+ * @attr ref android.R.styleable#GestureOverlayView_eventsInterceptionEnabled
+ * @attr ref android.R.styleable#GestureOverlayView_fadeDuration
+ * @attr ref android.R.styleable#GestureOverlayView_fadeOffset
+ * @attr ref android.R.styleable#GestureOverlayView_fadeEnabled
+ * @attr ref android.R.styleable#GestureOverlayView_gestureStrokeWidth
+ * @attr ref android.R.styleable#GestureOverlayView_gestureStrokeAngleThreshold
+ * @attr ref android.R.styleable#GestureOverlayView_gestureStrokeLengthThreshold
+ * @attr ref android.R.styleable#GestureOverlayView_gestureStrokeSquarenessThreshold
+ * @attr ref android.R.styleable#GestureOverlayView_gestureStrokeType 
+ * @attr ref android.R.styleable#GestureOverlayView_gestureColor
+ * @attr ref android.R.styleable#GestureOverlayView_uncertainGestureColor
+ */
+public class GestureOverlayView extends FrameLayout {
+    public static final int GESTURE_STROKE_TYPE_SINGLE = 0;
+    public static final int GESTURE_STROKE_TYPE_MULTIPLE = 1;
+
+    public static final int ORIENTATION_HORIZONTAL = 0;
+    public static final int ORIENTATION_VERTICAL = 1;
+
+    private static final int FADE_ANIMATION_RATE = 16;
+    private static final boolean GESTURE_RENDERING_ANTIALIAS = true;
+    private static final boolean DITHER_FLAG = true;
+
+    private final Paint mGesturePaint = new Paint();
+
+    private long mFadeDuration = 150;
+    private long mFadeOffset = 420;
+    private long mFadingStart;
+    private boolean mFadingHasStarted;
+    private boolean mFadeEnabled = true;
+
+    private int mCurrentColor;
+    private int mCertainGestureColor = 0xFFFFFF00;
+    private int mUncertainGestureColor = 0x48FFFF00;
+    private float mGestureStrokeWidth = 12.0f;
+    private int mInvalidateExtraBorder = 10;
+
+    private int mGestureStrokeType = GESTURE_STROKE_TYPE_SINGLE;
+    private float mGestureStrokeLengthThreshold = 30.0f;
+    private float mGestureStrokeSquarenessTreshold = 0.275f;
+    private float mGestureStrokeAngleThreshold = 40.0f;
+
+    private int mOrientation = ORIENTATION_VERTICAL;
+
+    private final Rect mInvalidRect = new Rect();
+    private final Path mPath = new Path();
+
+    private float mX;
+    private float mY;
+    
+    private float mCurveEndX;
+    private float mCurveEndY;
+
+    private float mTotalLength;
+    private boolean mIsGesturing = false;
+    private boolean mInterceptEvents = true;
+    private boolean mIsListeningForGestures;
+
+    // current gesture
+    private Gesture mCurrentGesture;
+    private final ArrayList<GesturePoint> mStrokeBuffer = new ArrayList<GesturePoint>(100);
+
+    // TODO: Make this a list of WeakReferences
+    private final ArrayList<OnGestureListener> mOnGestureListeners =
+            new ArrayList<OnGestureListener>();
+    // TODO: Make this a list of WeakReferences
+    private final ArrayList<OnGesturePerformedListener> mOnGesturePerformedListeners =
+            new ArrayList<OnGesturePerformedListener>();
+
+    private boolean mHandleGestureActions;
+
+    // fading out effect
+    private boolean mIsFadingOut = false;
+    private float mFadingAlpha = 1.0f;
+    private final AccelerateDecelerateInterpolator mInterpolator =
+            new AccelerateDecelerateInterpolator();
+
+    private final FadeOutRunnable mFadingOut = new FadeOutRunnable();
+
+    public GestureOverlayView(Context context) {
+        super(context);
+        init();
+    }
+
+    public GestureOverlayView(Context context, AttributeSet attrs) {
+        this(context, attrs, com.android.internal.R.attr.gestureOverlayViewStyle);
+    }
+
+    public GestureOverlayView(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+
+        TypedArray a = context.obtainStyledAttributes(attrs,
+                R.styleable.GestureOverlayView, defStyle, 0);
+
+        mGestureStrokeWidth = a.getFloat(R.styleable.GestureOverlayView_gestureStrokeWidth,
+                mGestureStrokeWidth);
+        mInvalidateExtraBorder = Math.max(1, ((int) mGestureStrokeWidth) - 1);
+        mCertainGestureColor = a.getColor(R.styleable.GestureOverlayView_gestureColor,
+                mCertainGestureColor);
+        mUncertainGestureColor = a.getColor(R.styleable.GestureOverlayView_uncertainGestureColor,
+                mUncertainGestureColor);
+        mFadeDuration = a.getInt(R.styleable.GestureOverlayView_fadeDuration, (int) mFadeDuration);
+        mFadeOffset = a.getInt(R.styleable.GestureOverlayView_fadeOffset, (int) mFadeOffset);
+        mGestureStrokeType = a.getInt(R.styleable.GestureOverlayView_gestureStrokeType,
+                mGestureStrokeType);
+        mGestureStrokeLengthThreshold = a.getFloat(
+                R.styleable.GestureOverlayView_gestureStrokeLengthThreshold,
+                mGestureStrokeLengthThreshold);
+        mGestureStrokeAngleThreshold = a.getFloat(
+                R.styleable.GestureOverlayView_gestureStrokeAngleThreshold,
+                mGestureStrokeAngleThreshold);
+        mGestureStrokeSquarenessTreshold = a.getFloat(
+                R.styleable.GestureOverlayView_gestureStrokeSquarenessThreshold,
+                mGestureStrokeSquarenessTreshold);
+        mInterceptEvents = a.getBoolean(R.styleable.GestureOverlayView_eventsInterceptionEnabled,
+                mInterceptEvents);
+        mFadeEnabled = a.getBoolean(R.styleable.GestureOverlayView_fadeEnabled,
+                mFadeEnabled);
+        mOrientation = a.getInt(R.styleable.GestureOverlayView_orientation, mOrientation);
+
+        a.recycle();
+
+        init();
+    }
+
+    private void init() {
+        setWillNotDraw(false);
+
+        final Paint gesturePaint = mGesturePaint;
+        gesturePaint.setAntiAlias(GESTURE_RENDERING_ANTIALIAS);
+        gesturePaint.setColor(mCertainGestureColor);
+        gesturePaint.setStyle(Paint.Style.STROKE);
+        gesturePaint.setStrokeJoin(Paint.Join.ROUND);
+        gesturePaint.setStrokeCap(Paint.Cap.ROUND);
+        gesturePaint.setStrokeWidth(mGestureStrokeWidth);
+        gesturePaint.setDither(DITHER_FLAG);
+
+        mCurrentColor = mCertainGestureColor;
+        setPaintAlpha(255);
+    }
+
+    public ArrayList<GesturePoint> getCurrentStroke() {
+        return mStrokeBuffer;
+    }
+
+    public int getOrientation() {
+        return mOrientation;
+    }
+
+    public void setOrientation(int orientation) {
+        mOrientation = orientation;
+    }
+
+    public void setGestureColor(int color) {
+        mCertainGestureColor = color;
+    }
+
+    public void setUncertainGestureColor(int color) {
+        mUncertainGestureColor = color;
+    }
+
+    public int getUncertainGestureColor() {
+        return mUncertainGestureColor;
+    }
+
+    public int getGestureColor() {
+        return mCertainGestureColor;
+    }
+
+    public float getGestureStrokeWidth() {
+        return mGestureStrokeWidth;
+    }
+
+    public void setGestureStrokeWidth(float gestureStrokeWidth) {
+        mGestureStrokeWidth = gestureStrokeWidth;
+        mInvalidateExtraBorder = Math.max(1, ((int) gestureStrokeWidth) - 1);
+        mGesturePaint.setStrokeWidth(gestureStrokeWidth);
+    }
+
+    public int getGestureStrokeType() {
+        return mGestureStrokeType;
+    }
+
+    public void setGestureStrokeType(int gestureStrokeType) {
+        mGestureStrokeType = gestureStrokeType;
+    }
+
+    public float getGestureStrokeLengthThreshold() {
+        return mGestureStrokeLengthThreshold;
+    }
+
+    public void setGestureStrokeLengthThreshold(float gestureStrokeLengthThreshold) {
+        mGestureStrokeLengthThreshold = gestureStrokeLengthThreshold;
+    }
+
+    public float getGestureStrokeSquarenessTreshold() {
+        return mGestureStrokeSquarenessTreshold;
+    }
+
+    public void setGestureStrokeSquarenessTreshold(float gestureStrokeSquarenessTreshold) {
+        mGestureStrokeSquarenessTreshold = gestureStrokeSquarenessTreshold;
+    }
+
+    public float getGestureStrokeAngleThreshold() {
+        return mGestureStrokeAngleThreshold;
+    }
+
+    public void setGestureStrokeAngleThreshold(float gestureStrokeAngleThreshold) {
+        mGestureStrokeAngleThreshold = gestureStrokeAngleThreshold;
+    }
+
+    public boolean isEventsInterceptionEnabled() {
+        return mInterceptEvents;
+    }
+
+    public void setEventsInterceptionEnabled(boolean enabled) {
+        mInterceptEvents = enabled;
+    }
+
+    public boolean isFadeEnabled() {
+        return mFadeEnabled;
+    }
+
+    public void setFadeEnabled(boolean fadeEnabled) {
+        mFadeEnabled = fadeEnabled;
+    }
+
+    public Gesture getGesture() {
+        return mCurrentGesture;
+    }
+
+    public void setGesture(Gesture gesture) {
+        if (mCurrentGesture != null) {
+            clear(false);
+        }
+
+        setCurrentColor(mCertainGestureColor);
+        mCurrentGesture = gesture;
+
+        final Path path = mCurrentGesture.toPath();
+        final RectF bounds = new RectF();
+        path.computeBounds(bounds, true);
+
+        mPath.rewind();
+        mPath.addPath(path, (getWidth() - bounds.width()) / 2.0f,
+                (getHeight() - bounds.height()) / 2.0f);
+
+        invalidate();
+    }
+
+    public void addOnGestureListener(OnGestureListener listener) {
+        mOnGestureListeners.add(listener);
+    }
+
+    public void removeOnGestureListener(OnGestureListener listener) {
+        mOnGestureListeners.remove(listener);
+    }
+
+    public void removeAllOnGestureListeners() {
+        mOnGestureListeners.clear();
+    }
+
+    public void addOnGesturePerformedListener(OnGesturePerformedListener listener) {
+        mOnGesturePerformedListeners.add(listener);
+        if (mOnGesturePerformedListeners.size() > 0) {
+            mHandleGestureActions = true;
+        }
+    }
+
+    public void removeOnGesturePerformedListener(OnGesturePerformedListener listener) {
+        mOnGesturePerformedListeners.remove(listener);
+        if (mOnGesturePerformedListeners.size() <= 0) {
+            mHandleGestureActions = false;
+        }
+    }
+
+    public void removeAllOnGesturePerformedListeners() {
+        mOnGesturePerformedListeners.clear();
+        mHandleGestureActions = false;
+    }
+
+    public boolean isGesturing() {
+        return mIsGesturing;
+    }
+
+    private void setCurrentColor(int color) {
+        mCurrentColor = color;
+        if (mFadingHasStarted) {
+            setPaintAlpha((int) (255 * mFadingAlpha));
+        } else {
+            setPaintAlpha(255);
+        }
+        invalidate();
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        super.draw(canvas);
+
+        if (mCurrentGesture != null) {
+            canvas.drawPath(mPath, mGesturePaint);
+        }
+    }
+
+    private void setPaintAlpha(int alpha) {
+        alpha += alpha >> 7;
+        final int baseAlpha = mCurrentColor >>> 24;
+        final int useAlpha = baseAlpha * alpha >> 8;
+        mGesturePaint.setColor((mCurrentColor << 8 >>> 8) | (useAlpha << 24));
+    }
+
+    public void clear(boolean animated) {
+        clear(animated, false);
+    }
+
+    private void clear(boolean animated, boolean fireActionPerformed) {
+        setPaintAlpha(255);
+        removeCallbacks(mFadingOut);
+        mFadingOut.fireActionPerformed = fireActionPerformed;
+
+        if (animated && mCurrentGesture != null) {
+            mFadingAlpha = 1.0f;
+            mIsFadingOut = true;
+            mFadingHasStarted = false;
+            mFadingStart = AnimationUtils.currentAnimationTimeMillis() + mFadeOffset;
+
+            postDelayed(mFadingOut, mFadeOffset);
+        } else {
+            mFadingAlpha = 1.0f;
+            mIsFadingOut = false;
+            mFadingHasStarted = false;
+
+            if (fireActionPerformed) {
+                post(mFadingOut);
+            } else {
+                mCurrentGesture = null;
+                mPath.rewind();
+                invalidate();
+            }
+        }
+    }
+
+    public void cancelClearAnimation() {
+        setPaintAlpha(255);
+        mIsFadingOut = false;
+        mFadingHasStarted = false;
+        removeCallbacks(mFadingOut);
+        mPath.rewind();
+        mCurrentGesture = null;
+    }
+
+    public void cancelGesture() {
+        mIsListeningForGestures = false;
+
+        // add the stroke to the current gesture
+        mCurrentGesture.addStroke(new GestureStroke(mStrokeBuffer));
+
+        // pass the event to handlers
+        final long now = SystemClock.uptimeMillis();
+        final MotionEvent event = MotionEvent.obtain(now, now,
+                MotionEvent.ACTION_CANCEL, 0.0f, 0.0f, 0);
+
+        final ArrayList<OnGestureListener> listeners = mOnGestureListeners;
+        final int count = listeners.size();
+        for (int i = 0; i < count; i++) {
+            listeners.get(i).onGestureCancelled(this, event);
+        }
+
+        event.recycle();
+
+        clear(false);
+        mIsGesturing = false;
+        mStrokeBuffer.clear();
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        cancelClearAnimation();
+    }
+
+    @Override
+    public boolean dispatchTouchEvent(MotionEvent event) {
+        if (isEnabled()) {
+            boolean cancelDispatch = (mIsGesturing || (mCurrentGesture != null &&
+                    mCurrentGesture.getStrokesCount() > 0)) && mInterceptEvents;
+            processEvent(event);
+
+            if (cancelDispatch) {
+                event.setAction(MotionEvent.ACTION_CANCEL);
+            }
+
+            super.dispatchTouchEvent(event);
+            return true;
+        }
+
+        return super.dispatchTouchEvent(event);
+    }
+
+    private boolean processEvent(MotionEvent event) {
+        switch (event.getAction()) {
+            case MotionEvent.ACTION_DOWN:
+                touchDown(event);
+                invalidate();
+                return true;
+            case MotionEvent.ACTION_MOVE:
+                if (mIsListeningForGestures) {
+                    Rect rect = touchMove(event);
+                    if (rect != null) {
+                        invalidate(rect);
+                    }
+                    return true;
+                }
+                break;
+            case MotionEvent.ACTION_UP:
+                if (mIsListeningForGestures) {
+                    touchUp(event, false);
+                    invalidate();
+                    return true;
+                }
+                break;
+            case MotionEvent.ACTION_CANCEL:
+                if (mIsListeningForGestures) {
+                    touchUp(event, true);
+                    invalidate();
+                    return true;
+                }
+        }
+
+        return false;
+    }
+
+    private void touchDown(MotionEvent event) {
+        mIsListeningForGestures = true;
+
+        float x = event.getX();
+        float y = event.getY();
+
+        mX = x;
+        mY = y;
+
+        mTotalLength = 0;
+        mIsGesturing = false;
+
+        if (mGestureStrokeType == GESTURE_STROKE_TYPE_SINGLE) {
+            if (mHandleGestureActions) setCurrentColor(mUncertainGestureColor);
+            mCurrentGesture = null;
+            mPath.rewind();
+        } else if (mCurrentGesture == null || mCurrentGesture.getStrokesCount() == 0) {
+            if (mHandleGestureActions) setCurrentColor(mUncertainGestureColor);
+        }
+
+        // if there is fading out going on, stop it.
+        if (mFadingHasStarted) {
+            cancelClearAnimation();
+        } else if (mIsFadingOut) {
+            setPaintAlpha(255);
+            mIsFadingOut = false;
+            mFadingHasStarted = false;
+            removeCallbacks(mFadingOut);
+        }
+
+        if (mCurrentGesture == null) {
+            mCurrentGesture = new Gesture();
+        }
+
+        mStrokeBuffer.add(new GesturePoint(x, y, event.getEventTime()));
+        mPath.moveTo(x, y);
+
+        final int border = mInvalidateExtraBorder;
+        mInvalidRect.set((int) x - border, (int) y - border, (int) x + border, (int) y + border);
+
+        mCurveEndX = x;
+        mCurveEndY = y;
+
+        // pass the event to handlers
+        final ArrayList<OnGestureListener> listeners = mOnGestureListeners;
+        final int count = listeners.size();
+        for (int i = 0; i < count; i++) {
+            listeners.get(i).onGestureStarted(this, event);
+        }        
+    }
+
+    private Rect touchMove(MotionEvent event) {
+        Rect areaToRefresh = null;
+        
+        final float x = event.getX();
+        final float y = event.getY();
+
+        final float previousX = mX;
+        final float previousY = mY;
+
+        final float dx = Math.abs(x - previousX);
+        final float dy = Math.abs(y - previousY);
+        
+        if (dx >= GestureStroke.TOUCH_TOLERANCE || dy >= GestureStroke.TOUCH_TOLERANCE) {
+            areaToRefresh = mInvalidRect;
+
+            // start with the curve end
+            final int border = mInvalidateExtraBorder;
+            areaToRefresh.set((int) mCurveEndX - border, (int) mCurveEndY - border,
+                    (int) mCurveEndX + border, (int) mCurveEndY + border);
+            
+            float cX = mCurveEndX = (x + previousX) / 2;
+            float cY = mCurveEndY = (y + previousY) / 2;
+
+            mPath.quadTo(previousX, previousY, cX, cY);
+            
+            // union with the control point of the new curve
+            areaToRefresh.union((int) previousX - border, (int) previousY - border,
+                    (int) previousX + border, (int) previousY + border);
+            
+            // union with the end point of the new curve
+            areaToRefresh.union((int) cX - border, (int) cY - border,
+                    (int) cX + border, (int) cY + border);
+
+            mX = x;
+            mY = y;
+        }
+
+        mStrokeBuffer.add(new GesturePoint(x, y, event.getEventTime()));
+
+        if (mHandleGestureActions && !mIsGesturing) {
+            mTotalLength += (float) Math.sqrt(dx * dx + dy * dy);
+
+            if (mTotalLength > mGestureStrokeLengthThreshold) {
+                final OrientedBoundingBox box =
+                        GestureUtilities.computeOrientedBoundingBox(mStrokeBuffer);
+
+                float angle = Math.abs(box.orientation);
+                if (angle > 90) {
+                    angle = 180 - angle;
+                }
+
+                if (box.squareness > mGestureStrokeSquarenessTreshold ||
+                        (mOrientation == ORIENTATION_VERTICAL ?
+                                angle < mGestureStrokeAngleThreshold :
+                                angle > mGestureStrokeAngleThreshold)) {
+
+                    mIsGesturing = true;
+                    setCurrentColor(mCertainGestureColor);
+                }
+            }
+        }
+
+        // pass the event to handlers
+        final ArrayList<OnGestureListener> listeners = mOnGestureListeners;
+        final int count = listeners.size();
+        for (int i = 0; i < count; i++) {
+            listeners.get(i).onGesture(this, event);
+        }        
+
+        return areaToRefresh;
+    }
+
+    private void touchUp(MotionEvent event, boolean cancel) {
+        mIsListeningForGestures = false;
+
+        // add the stroke to the current gesture
+        mCurrentGesture.addStroke(new GestureStroke(mStrokeBuffer));
+        mStrokeBuffer.clear();
+
+        if (!cancel) {
+            // pass the event to handlers
+            final ArrayList<OnGestureListener> listeners = mOnGestureListeners;
+            int count = listeners.size();
+            for (int i = 0; i < count; i++) {
+                listeners.get(i).onGestureEnded(this, event);
+            }
+
+            if (mHandleGestureActions) {
+                clear(mFadeEnabled, mIsGesturing);
+            }
+        } else {
+            // pass the event to handlers
+            final ArrayList<OnGestureListener> listeners = mOnGestureListeners;
+            final int count = listeners.size();
+            for (int i = 0; i < count; i++) {
+                listeners.get(i).onGestureCancelled(this, event);
+            }
+
+            clear(false);
+        }
+
+        mIsGesturing = false;
+    }
+
+    private void fireOnGesturePerformed() {
+        final ArrayList<OnGesturePerformedListener> actionListeners =
+                mOnGesturePerformedListeners;
+        final int count = actionListeners.size();
+        for (int i = 0; i < count; i++) {
+            actionListeners.get(i).onGesturePerformed(GestureOverlayView.this,
+                    mCurrentGesture);
+        }
+    }
+
+    private class FadeOutRunnable implements Runnable {
+        boolean fireActionPerformed;
+
+        public void run() {
+            if (mIsFadingOut) {
+                final long now = AnimationUtils.currentAnimationTimeMillis();
+                final long duration = now - mFadingStart;
+
+                if (duration > mFadeDuration) {
+                    if (fireActionPerformed) {
+                        fireOnGesturePerformed();
+                    }
+
+                    mIsFadingOut = false;
+                    mFadingHasStarted = false;
+                    mPath.rewind();
+                    mCurrentGesture = null;
+                    setPaintAlpha(255);
+                } else {
+                    mFadingHasStarted = true;
+                    float interpolatedTime = Math.max(0.0f,
+                            Math.min(1.0f, duration / (float) mFadeDuration));
+                    mFadingAlpha = 1.0f - mInterpolator.getInterpolation(interpolatedTime);
+                    setPaintAlpha((int) (255 * mFadingAlpha));
+                    postDelayed(this, FADE_ANIMATION_RATE);
+                }
+            } else {
+                fireOnGesturePerformed();
+
+                mFadingHasStarted = false;
+                mPath.rewind();
+                mCurrentGesture = null;
+                setPaintAlpha(255);
+            }
+
+            invalidate();            
+        }
+    }
+
+    public static interface OnGestureListener {
+        void onGestureStarted(GestureOverlayView overlay, MotionEvent event);
+
+        void onGesture(GestureOverlayView overlay, MotionEvent event);
+
+        void onGestureEnded(GestureOverlayView overlay, MotionEvent event);
+
+        void onGestureCancelled(GestureOverlayView overlay, MotionEvent event);
+    }
+
+    public static interface OnGesturePerformedListener {
+        void onGesturePerformed(GestureOverlayView overlay, Gesture gesture);
+    }
+}
diff --git a/tests/sketch/src/com/android/gesture/GesturePoint.java b/core/java/android/gesture/GesturePoint.java
similarity index 69%
rename from tests/sketch/src/com/android/gesture/GesturePoint.java
rename to core/java/android/gesture/GesturePoint.java
index 81e59a4..3698011 100644
--- a/tests/sketch/src/com/android/gesture/GesturePoint.java
+++ b/core/java/android/gesture/GesturePoint.java
@@ -14,7 +14,10 @@
  * limitations under the License.
  */
 
-package com.android.gesture;
+package android.gesture;
+
+import java.io.DataInputStream;
+import java.io.IOException;
 
 /**
  * A timed point of a gesture stroke
@@ -31,4 +34,13 @@
         this.y = y;
         timestamp = t;
     }
+
+    static GesturePoint deserialize(DataInputStream in) throws IOException {
+        // Read X and Y
+        final float x = in.readFloat();
+        final float y = in.readFloat();
+        // Read timestamp
+        final long timeStamp = in.readLong();
+        return new GesturePoint(x, y, timeStamp);
+    }
 }
diff --git a/core/java/android/gesture/GestureStroke.java b/core/java/android/gesture/GestureStroke.java
new file mode 100644
index 0000000..0d7bc2d0
--- /dev/null
+++ b/core/java/android/gesture/GestureStroke.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.gesture;
+
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.RectF;
+
+import java.io.IOException;
+import java.io.DataOutputStream;
+import java.io.DataInputStream;
+import java.util.ArrayList;
+
+/**
+ * A gesture stroke started on a touch down and ended on a touch up.
+ */
+public class GestureStroke {
+    static final float TOUCH_TOLERANCE = 3;
+
+    public final RectF boundingBox;
+
+    public final float length;
+    public final float[] points;
+
+    private final long[] timestamps;
+    private Path mCachedPath;
+
+    /**
+     * Construct a gesture stroke from a list of gesture points
+     * 
+     * @param points
+     */
+    public GestureStroke(ArrayList<GesturePoint> points) {
+        final int count = points.size();
+        final float[] tmpPoints = new float[count * 2];
+        final long[] times = new long[count];
+
+        RectF bx = null;
+        float len = 0;
+        int index = 0;
+
+        for (int i = 0; i < count; i++) {
+            final GesturePoint p = points.get(i);
+            tmpPoints[i * 2] = p.x;
+            tmpPoints[i * 2 + 1] = p.y;
+            times[index] = p.timestamp;
+
+            if (bx == null) {
+                bx = new RectF();
+                bx.top = p.y;
+                bx.left = p.x;
+                bx.right = p.x;
+                bx.bottom = p.y;
+                len = 0;
+            } else {
+                len += Math.sqrt(Math.pow(p.x - tmpPoints[(i - 1) * 2], 2)
+                        + Math.pow(p.y - tmpPoints[(i -1 ) * 2 + 1], 2));
+                bx.union(p.x, p.y);
+            }
+            index++;
+        }
+        
+        timestamps = times;
+        this.points = tmpPoints;
+        boundingBox = bx;
+        length = len;
+    }
+
+    /**
+     * Draw the gesture with a given canvas and paint
+     * 
+     * @param canvas
+     */
+    void draw(Canvas canvas, Paint paint) {
+        if (mCachedPath == null) {
+            makePath();
+        }
+
+        canvas.drawPath(mCachedPath, paint);
+    }
+
+    public Path getPath() {
+        if (mCachedPath == null) {
+            makePath();
+        }
+
+        return mCachedPath;
+    }
+
+    private void makePath() {
+        final float[] localPoints = points;
+        final int count = localPoints.length;
+
+        Path path = null;
+
+        float mX = 0;
+        float mY = 0;
+
+        for (int i = 0; i < count; i += 2) {
+            float x = localPoints[i];
+            float y = localPoints[i + 1];
+            if (path == null) {
+                path = new Path();
+                path.moveTo(x, y);
+                mX = x;
+                mY = y;
+            } else {
+                float dx = Math.abs(x - mX);
+                float dy = Math.abs(y - mY);
+                if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
+                    path.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
+                    mX = x;
+                    mY = y;
+                }
+            }
+        }
+
+        mCachedPath = path;
+    }
+
+    /**
+     * Convert the stroke to a Path based on the number of points
+     * 
+     * @param width the width of the bounding box of the target path
+     * @param height the height of the bounding box of the target path
+     * @param numSample the number of points needed
+     * 
+     * @return the path
+     */
+    public Path toPath(float width, float height, int numSample) {
+        final float[] pts = GestureUtilities.temporalSampling(this, numSample);
+        final RectF rect = boundingBox;
+
+        final Matrix matrix = new Matrix();
+        matrix.setTranslate(-rect.left, -rect.top);
+        matrix.postScale(width / rect.width(), height / rect.height());
+        matrix.mapPoints(pts);
+
+        float mX = 0;
+        float mY = 0;
+
+        Path path = null;
+
+        final int count = pts.length;
+
+        for (int i = 0; i < count; i += 2) {
+            float x = pts[i];
+            float y = pts[i + 1];
+            if (path == null) {
+                path = new Path();
+                path.moveTo(x, y);
+                mX = x;
+                mY = y;
+            } else {
+                float dx = Math.abs(x - mX);
+                float dy = Math.abs(y - mY);
+                if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
+                    path.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
+                    mX = x;
+                    mY = y;
+                }
+            }
+        }
+
+        return path;
+    }
+
+    void serialize(DataOutputStream out) throws IOException {
+        final float[] pts = points;
+        final long[] times = timestamps;
+        final int count = points.length;
+
+        // Write number of points
+        out.writeInt(count / 2);
+
+        for (int i = 0; i < count; i += 2) {
+            // Write X
+            out.writeFloat(pts[i]);
+            // Write Y
+            out.writeFloat(pts[i + 1]);
+            // Write timestamp
+            out.writeLong(times[i / 2]);
+        }
+    }
+
+    static GestureStroke deserialize(DataInputStream in) throws IOException {
+        // Number of points
+        final int count = in.readInt();
+
+        final ArrayList<GesturePoint> points = new ArrayList<GesturePoint>(count);
+        for (int i = 0; i < count; i++) {
+            points.add(GesturePoint.deserialize(in));
+        }
+
+        return new GestureStroke(points);
+    }    
+
+    /**
+     * Invalidate the cached path that is used to render the stroke
+     */
+    public void clearPath() {
+        if (mCachedPath != null) mCachedPath.rewind();
+    }
+    
+    /**
+     * Compute an oriented bounding box of the stroke
+     * @return OrientedBoundingBox
+     */
+    public OrientedBoundingBox computeOrientedBoundingBox() {
+        return GestureUtilities.computeOrientedBoundingBox(points);
+    }
+}
diff --git a/tests/sketch/src/com/android/gesture/GestureUtilities.java b/core/java/android/gesture/GestureUtilities.java
similarity index 89%
rename from tests/sketch/src/com/android/gesture/GestureUtilities.java
rename to core/java/android/gesture/GestureUtilities.java
index 2798616..4a3144c2 100755
--- a/tests/sketch/src/com/android/gesture/GestureUtilities.java
+++ b/core/java/android/gesture/GestureUtilities.java
@@ -14,19 +14,20 @@
  * limitations under the License.
  */
 
-package com.android.gesture;
+package android.gesture;
 
 import android.graphics.RectF;
 import android.graphics.Matrix;
+import android.util.Log;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.io.Closeable;
 import java.io.IOException;
 
-import static com.android.gesture.GestureConstants.*;
+import static android.gesture.GestureConstants.*;
 
-public final class GestureUtilities {
+final class GestureUtilities {
     private static final int TEMPORAL_SAMPLING_RATE = 16;
 
     private GestureUtilities() {
@@ -42,7 +43,7 @@
             try {
                 stream.close();
             } catch (IOException e) {
-                android.util.Log.e(LOG_TAG, "Could not close stream", e);
+                Log.e(LOG_TAG, "Could not close stream", e);
             }
         }
     }
@@ -56,25 +57,31 @@
         float sx = targetPatchSize / rect.width();
         float sy = targetPatchSize / rect.height();
         float scale = sx < sy ? sx : sy;
-        android.graphics.Matrix trans = new android.graphics.Matrix();
-        trans.setScale(scale, scale);
-        android.graphics.Matrix translate1 = new android.graphics.Matrix();
-        translate1.setTranslate(-rect.centerX(), -rect.centerY());
-        trans.preConcat(translate1);
-        android.graphics.Matrix translate2 = new android.graphics.Matrix();
-        translate2.setTranslate(targetPatchSize / 2, targetPatchSize / 2);
-        trans.postConcat(translate2);
 
-        ArrayList<GestureStroke> strokes = gesture.getStrokes();
-        int count = strokes.size();
+        float preDx = -rect.centerX();
+        float preDy = -rect.centerY();
+        float postDx = targetPatchSize / 2;
+        float postDy = targetPatchSize / 2;
+
+        final ArrayList<GestureStroke> strokes = gesture.getStrokes();
+        final int count = strokes.size();
+
         int size;
         float xpos;
         float ypos;
+
         for (int index = 0; index < count; index++) {
-            GestureStroke stroke = strokes.get(index);
-            size = stroke.points.length;
-            float[] pts = new float[size];
-            trans.mapPoints(pts, 0, stroke.points, 0, size / 2);
+            final GestureStroke stroke = strokes.get(index);
+            float[] strokepoints = stroke.points;
+            size = strokepoints.length;
+
+            final float[] pts = new float[size];
+             
+            for (int i = 0; i < size; i += 2) {
+                pts[i] = (strokepoints[i] + preDx) * scale + postDx;
+                pts[i + 1] = (strokepoints[i + 1] + preDy) * scale + postDy;
+            }
+        
             float segmentEndX = -1;
             float segmentEndY = -1;
             
@@ -348,33 +355,31 @@
     /**
      * Calculate the cosine distance between two instances
      * 
-     * @param in1
-     * @param in2
+     * @param vector1
+     * @param vector2
      * @return the distance between 0 and Math.PI
      */
-    static double cosineDistance(Instance in1, Instance in2) {
+    static double cosineDistance(float[] vector1, float[] vector2) {
         float sum = 0;
-        float[] vector1 = in1.vector;
-        float[] vector2 = in2.vector;
         int len = vector1.length;
         for (int i = 0; i < len; i++) {
             sum += vector1[i] * vector2[i];
         }
-        return Math.acos(sum / (in1.magnitude * in2.magnitude));
+        return Math.acos(sum);
     }
 
-    public static OrientedBoundingBox computeOrientedBoundingBox(ArrayList<GesturePoint> pts) {
+    static OrientedBoundingBox computeOrientedBoundingBox(ArrayList<GesturePoint> pts) {
         GestureStroke stroke = new GestureStroke(pts);
         float[] points = temporalSampling(stroke, TEMPORAL_SAMPLING_RATE);
         return computeOrientedBoundingBox(points);
     }
 
-    public static OrientedBoundingBox computeOrientedBoundingBox(float[] points) {
+    static OrientedBoundingBox computeOrientedBoundingBox(float[] points) {
         float[] meanVector = computeCentroid(points);
         return computeOrientedBoundingBox(points, meanVector);
     }
 
-    public static OrientedBoundingBox computeOrientedBoundingBox(float[] points, float[] centroid) {
+    static OrientedBoundingBox computeOrientedBoundingBox(float[] points, float[] centroid) {
         Matrix tr = new Matrix();
         tr.setTranslate(-centroid[0], -centroid[1]);
         tr.mapPoints(points);
@@ -388,7 +393,7 @@
         } else { // -PI<alpha<PI
             angle = (float) Math.atan2(targetVector[1], targetVector[0]);
             angle = (float) (180 * angle / Math.PI);
-            android.graphics.Matrix trans = new android.graphics.Matrix();
+            Matrix trans = new Matrix();
             trans.setRotate(-angle);
             trans.mapPoints(points);
         }
diff --git a/tests/sketch/src/com/android/gesture/Instance.java b/core/java/android/gesture/Instance.java
similarity index 72%
rename from tests/sketch/src/com/android/gesture/Instance.java
rename to core/java/android/gesture/Instance.java
index 011d1fc..7922fab 100755
--- a/tests/sketch/src/com/android/gesture/Instance.java
+++ b/core/java/android/gesture/Instance.java
@@ -14,7 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.gesture;
+package android.gesture;
+
+import android.graphics.Matrix;
 
 /**
  * An instance represents a sample if the label is available or a query if the
@@ -23,7 +25,7 @@
 class Instance {
     private static final int SEQUENCE_SAMPLE_SIZE = 16;
 
-    private static final int PATCH_SAMPLE_SIZE = 8;
+    private static final int PATCH_SAMPLE_SIZE = 16;
 
     private final static float[] ORIENTATIONS = {
             0, 45, 90, 135, 180, -0, -45, -90, -135, -180
@@ -35,22 +37,28 @@
     // the label can be null
     final String label;
 
-    // the length of the vector
-    final float magnitude;
-
     // the id of the instance
     final long id;
-
+    
     private Instance(long id, float[] sample, String sampleName) {
         this.id = id;
         vector = sample;
         label = sampleName;
+    }
+    
+    private void normalize() {
+        float[] sample = vector;
         float sum = 0;
+
         int size = sample.length;
         for (int i = 0; i < size; i++) {
             sum += sample[i] * sample[i];
         }
-        magnitude = (float) Math.sqrt(sum);
+
+        float magnitude = (float) Math.sqrt(sum);
+        for (int i = 0; i < size; i++) {
+            sample[i] /= magnitude;
+        }
     }
 
     /**
@@ -60,21 +68,25 @@
      * @param label
      * @return the instance
      */
-    static Instance createInstance(GestureLibrary gesturelib, Gesture gesture, String label) {
+    static Instance createInstance(int samplingType, Gesture gesture, String label) {
         float[] pts;
-        if (gesturelib.getGestureType() == GestureLibrary.SEQUENCE_SENSITIVE) {
-            pts = temporalSampler(gesturelib, gesture);
+        Instance instance;
+        if (samplingType == GestureLibrary.SEQUENCE_SENSITIVE) {
+            pts = temporalSampler(samplingType, gesture);
+            instance = new Instance(gesture.getID(), pts, label);
+            instance.normalize();
         } else {
             pts = spatialSampler(gesture);
+            instance = new Instance(gesture.getID(), pts, label);
         }
-        return new Instance(gesture.getID(), pts, label);
+        return instance;
     }
-
+    
     private static float[] spatialSampler(Gesture gesture) {
         return GestureUtilities.spatialSampling(gesture, PATCH_SAMPLE_SIZE);
     }
 
-    private static float[] temporalSampler(GestureLibrary gesturelib, Gesture gesture) {
+    private static float[] temporalSampler(int samplingType, Gesture gesture) {
         float[] pts = GestureUtilities.temporalSampling(gesture.getStrokes().get(0),
                 SEQUENCE_SAMPLE_SIZE);
         float[] center = GestureUtilities.computeCentroid(pts);
@@ -82,7 +94,7 @@
         orientation *= 180 / Math.PI;
 
         float adjustment = -orientation;
-        if (gesturelib.getOrientationStyle() == GestureLibrary.ORIENTATION_SENSITIVE) {
+        if (samplingType == GestureLibrary.ORIENTATION_SENSITIVE) {
             int count = ORIENTATIONS.length;
             for (int i = 0; i < count; i++) {
                 float delta = ORIENTATIONS[i] - orientation;
@@ -92,12 +104,11 @@
             }
         }
 
-        android.graphics.Matrix m = new android.graphics.Matrix();
+        Matrix m = new Matrix();
         m.setTranslate(-center[0], -center[1]);
-        android.graphics.Matrix rotation = new android.graphics.Matrix();
-        rotation.setRotate(adjustment);
-        m.postConcat(rotation);
+        m.postRotate(adjustment);
         m.mapPoints(pts);
+
         return pts;
     }
 
diff --git a/tests/sketch/src/com/android/gesture/InstanceLearner.java b/core/java/android/gesture/InstanceLearner.java
similarity index 71%
rename from tests/sketch/src/com/android/gesture/InstanceLearner.java
rename to core/java/android/gesture/InstanceLearner.java
index 335719a..1739cdc 100644
--- a/tests/sketch/src/com/android/gesture/InstanceLearner.java
+++ b/core/java/android/gesture/InstanceLearner.java
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-package com.android.gesture;
+package android.gesture;
 
 import android.util.Config;
 import android.util.Log;
+import static android.gesture.GestureConstants.*;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -30,25 +31,22 @@
  */
 
 class InstanceLearner extends Learner {
-
-    private static final String LOGTAG = "InstanceLearner";
-
     @Override
-    ArrayList<Prediction> classify(GestureLibrary lib, Instance instance) {
+    ArrayList<Prediction> classify(int gestureType, float[] vector) {
         ArrayList<Prediction> predictions = new ArrayList<Prediction>();
         ArrayList<Instance> instances = getInstances();
         int count = instances.size();
         TreeMap<String, Double> label2score = new TreeMap<String, Double>();
         for (int i = 0; i < count; i++) {
             Instance sample = instances.get(i);
-            if (sample.vector.length != instance.vector.length) {
+            if (sample.vector.length != vector.length) {
                 continue;
             }
             double distance;
-            if (lib.getGestureType() == GestureLibrary.SEQUENCE_SENSITIVE) {
-                distance = GestureUtilities.cosineDistance(sample, instance);
+            if (gestureType == GestureLibrary.SEQUENCE_SENSITIVE) {
+                distance = GestureUtilities.cosineDistance(sample.vector, vector);
             } else {
-                distance = GestureUtilities.squaredEuclideanDistance(sample.vector, instance.vector);
+                distance = GestureUtilities.squaredEuclideanDistance(sample.vector, vector);
             }
             double weight;
             if (distance == 0) {
@@ -63,19 +61,15 @@
         }
 
         double sum = 0;
-        Iterator<String> lableIterator = label2score.keySet().iterator();
-        while (lableIterator.hasNext()) {
-            String name = lableIterator.next();
+        for (String name : label2score.keySet()) {
             double score = label2score.get(name);
             sum += score;
             predictions.add(new Prediction(name, score));
         }
 
         // normalize
-        Iterator<Prediction> predictionIterator = predictions.iterator();
-        while (predictionIterator.hasNext()) {
-            Prediction name = predictionIterator.next();
-            name.score /= sum;
+        for (Prediction prediction : predictions) {
+            prediction.score /= sum;
         }
 
         Collections.sort(predictions, new Comparator<Prediction>() {
@@ -92,14 +86,6 @@
             }
         });
 
-        if (Config.DEBUG) {
-            predictionIterator = predictions.iterator();
-            while (predictionIterator.hasNext()) {
-                Prediction name = predictionIterator.next();
-                Log.v(LOGTAG, "prediction [" + name.name + " = " + name.score + "]");
-            }
-        }
-
         return predictions;
     }
 }
diff --git a/tests/sketch/src/com/android/gesture/Learner.java b/core/java/android/gesture/Learner.java
similarity index 94%
rename from tests/sketch/src/com/android/gesture/Learner.java
rename to core/java/android/gesture/Learner.java
index b4183d2..feacde5 100755
--- a/tests/sketch/src/com/android/gesture/Learner.java
+++ b/core/java/android/gesture/Learner.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.gesture;
+package android.gesture;
 
 import java.util.ArrayList;
 
@@ -79,5 +79,5 @@
         instances.removeAll(toDelete);
     }
 
-    abstract ArrayList<Prediction> classify(GestureLibrary library, Instance instance);
+    abstract ArrayList<Prediction> classify(int gestureType, float[] vector);
 }
diff --git a/core/java/android/gesture/LetterRecognizer.java b/core/java/android/gesture/LetterRecognizer.java
new file mode 100644
index 0000000..b26b3f2
--- /dev/null
+++ b/core/java/android/gesture/LetterRecognizer.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.gesture;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+
+import java.io.BufferedInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+
+import static android.gesture.GestureConstants.LOG_TAG;
+
+public class LetterRecognizer {
+    public final static int RECOGNIZER_LATIN_LOWERCASE = 0;
+    static final String GESTURE_FILE_NAME = "letters.gestures";
+
+    private final static int ADJUST_RANGE = 3;    
+
+    private SigmoidUnit[] mHiddenLayer;
+    private SigmoidUnit[] mOutputLayer;
+
+    private final String[] mClasses;
+
+    private final int mPatchSize;
+    
+    private GestureLibrary mGestureLibrary;
+
+    private final Comparator<Prediction> mComparator = new PredictionComparator();
+
+    private static class SigmoidUnit {
+        final float[] mWeights;
+
+        SigmoidUnit(float[] weights) {
+            mWeights = weights;
+        }
+
+        private float compute(float[] inputs) {
+            float sum = 0;
+
+            final int count = inputs.length;
+            final float[] weights = mWeights;
+
+            for (int i = 0; i < count; i++) {
+                sum += inputs[i] * weights[i];
+            }
+            sum += weights[weights.length - 1];
+
+            return 1.0f / (float) (1 + Math.exp(-sum));
+        }
+    }
+
+    public static LetterRecognizer getLetterRecognizer(Context context, int type) {
+        switch (type) {
+            case RECOGNIZER_LATIN_LOWERCASE: {
+                return createFromResource(context, com.android.internal.R.raw.latin_lowercase);
+            }
+        }
+        return null;
+    }
+
+    private LetterRecognizer(int numOfInput, int numOfHidden, String[] classes) {
+        mPatchSize = (int) Math.sqrt(numOfInput);
+        mHiddenLayer = new SigmoidUnit[numOfHidden];
+        mClasses = classes;
+        mOutputLayer = new SigmoidUnit[classes.length];
+    }
+
+    public ArrayList<Prediction> recognize(Gesture gesture) {
+        return recognize(gesture, null);
+    }
+
+    public ArrayList<Prediction> recognize(Gesture gesture, ArrayList<Prediction> predictions) {
+        float[] query = GestureUtilities.spatialSampling(gesture, mPatchSize);
+        predictions = classify(query, predictions);
+        adjustPrediction(gesture, predictions);
+        return predictions;
+    }
+
+    private ArrayList<Prediction> classify(float[] vector, ArrayList<Prediction> predictions) {
+        if (predictions == null) {
+            predictions = new ArrayList<Prediction>();
+        } else {
+            predictions.clear();
+        }
+
+        final float[] intermediateOutput = compute(mHiddenLayer, vector);
+        final float[] output = compute(mOutputLayer, intermediateOutput);
+
+        double sum = 0;
+
+        final String[] classes = mClasses;
+        final int count = classes.length;
+
+        for (int i = 0; i < count; i++) {
+            double score = output[i];
+            sum += score;
+            predictions.add(new Prediction(classes[i], score));
+        }
+
+        for (int i = 0; i < count; i++) {
+            predictions.get(i).score /= sum;
+        }
+
+        Collections.sort(predictions, mComparator);
+
+        return predictions;
+    }
+
+    private float[] compute(SigmoidUnit[] layer, float[] input) {
+        final float[] output = new float[layer.length];
+        final int count = layer.length;
+
+        for (int i = 0; i < count; i++) {
+            output[i] = layer[i].compute(input);
+        }
+
+        return output;
+    }
+
+    private static LetterRecognizer createFromResource(Context context, int resourceID) {
+        final Resources resources = context.getResources();
+
+        DataInputStream in = null;
+        LetterRecognizer classifier = null;
+
+        try {
+            in = new DataInputStream(new BufferedInputStream(resources.openRawResource(resourceID),
+                    GestureConstants.IO_BUFFER_SIZE));
+
+            final int version = in.readShort();
+
+            switch (version) {
+                case 1:
+                    classifier = readV1(in);
+                    break;
+            }
+
+        } catch (IOException e) {
+            Log.d(LOG_TAG, "Failed to load handwriting data:", e);
+        } finally {
+            GestureUtilities.closeStream(in);
+        }
+
+        return classifier;
+    }
+
+    private static LetterRecognizer readV1(DataInputStream in) throws IOException {
+
+        final int iCount = in.readInt();
+        final int hCount = in.readInt();
+        final int oCount = in.readInt();
+
+        final String[] classes = new String[oCount];
+        for (int i = 0; i < classes.length; i++) {
+            classes[i] = in.readUTF();
+        }
+
+        final LetterRecognizer classifier = new LetterRecognizer(iCount, hCount, classes);
+        final SigmoidUnit[] hiddenLayer = new SigmoidUnit[hCount];
+        final SigmoidUnit[] outputLayer = new SigmoidUnit[oCount];
+
+        for (int i = 0; i < hCount; i++) {
+            final float[] weights = new float[iCount + 1];
+            for (int j = 0; j <= iCount; j++) {
+                weights[j] = in.readFloat();
+            }
+            hiddenLayer[i] = new SigmoidUnit(weights);
+        }
+
+        for (int i = 0; i < oCount; i++) {
+            final float[] weights = new float[hCount + 1];
+            for (int j = 0; j <= hCount; j++) {
+                weights[j] = in.readFloat();
+            }
+            outputLayer[i] = new SigmoidUnit(weights);
+        }
+
+        classifier.mHiddenLayer = hiddenLayer;
+        classifier.mOutputLayer = outputLayer;
+
+        return classifier;
+    }
+
+    /**
+     * TODO: Publish this API once we figure out where we should save the personzlied
+     * gestures, and how to do so across all apps
+     *
+     * @hide
+     */
+    public boolean save() {
+        if (mGestureLibrary != null) {
+            return mGestureLibrary.save();
+        }
+        return false;
+    }
+
+    /**
+     * TODO: Publish this API once we figure out where we should save the personzlied
+     * gestures, and how to do so across all apps
+     *
+     * @hide
+     */
+    public void setPersonalizationEnabled(boolean enabled) {
+        if (enabled) {
+            mGestureLibrary = new GestureLibrary(GESTURE_FILE_NAME);
+            mGestureLibrary.setSequenceType(GestureLibrary.SEQUENCE_INVARIANT);
+            mGestureLibrary.load();
+        } else {
+            mGestureLibrary = null;
+        }
+    }
+
+    /**
+     * TODO: Publish this API once we figure out where we should save the personzlied
+     * gestures, and how to do so across all apps
+     *
+     * @hide
+     */
+    public void addExample(String letter, Gesture example) {
+        if (mGestureLibrary != null) {
+            mGestureLibrary.addGesture(letter, example);
+        }
+    }
+    
+    private void adjustPrediction(Gesture query, ArrayList<Prediction> predictions) {
+        if (mGestureLibrary != null) {
+            final ArrayList<Prediction> results = mGestureLibrary.recognize(query);
+            final HashMap<String, Prediction> topNList = new HashMap<String, Prediction>();
+
+            for (int j = 0; j < ADJUST_RANGE; j++) {
+                Prediction prediction = predictions.remove(0);
+                topNList.put(prediction.name, prediction);
+            }
+
+            final int count = results.size();
+            for (int j = count - 1; j >= 0 && !topNList.isEmpty(); j--) {
+                final Prediction item = results.get(j);
+                final Prediction original = topNList.get(item.name);
+                if (original != null) {
+                    predictions.add(0, original);
+                    topNList.remove(item.name);
+                }
+            }
+        }
+    }
+
+    private static class PredictionComparator implements Comparator<Prediction> {
+        public int compare(Prediction object1, Prediction object2) {
+            double score1 = object1.score;
+            double score2 = object2.score;
+            if (score1 > score2) {
+                return -1;
+            } else if (score1 < score2) {
+                return 1;
+            } else {
+                return 0;
+            }
+        }
+    }
+}
diff --git a/tests/sketch/src/com/android/gesture/OrientedBoundingBox.java b/core/java/android/gesture/OrientedBoundingBox.java
similarity index 94%
rename from tests/sketch/src/com/android/gesture/OrientedBoundingBox.java
rename to core/java/android/gesture/OrientedBoundingBox.java
index a07d125..f1335ee 100644
--- a/tests/sketch/src/com/android/gesture/OrientedBoundingBox.java
+++ b/core/java/android/gesture/OrientedBoundingBox.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.gesture;
+package android.gesture;
 
 import android.graphics.Matrix;
 import android.graphics.Path;
@@ -47,6 +47,11 @@
         }
     }
 
+    /**
+     * Currently used for debugging purpose only.
+     *
+     * @hide
+     */
     public Path toPath() {
         Path path = new Path();
         float[] point = new float[2];
diff --git a/tests/sketch/src/com/android/gesture/Prediction.java b/core/java/android/gesture/Prediction.java
similarity index 96%
rename from tests/sketch/src/com/android/gesture/Prediction.java
rename to core/java/android/gesture/Prediction.java
index 92d3ba4..ce6ad57 100755
--- a/tests/sketch/src/com/android/gesture/Prediction.java
+++ b/core/java/android/gesture/Prediction.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.gesture;
+package android.gesture;
 
 public class Prediction {
     public final String name;
diff --git a/core/java/android/hardware/ISensorService.aidl b/core/java/android/hardware/ISensorService.aidl
index 04af2ae..67180bd 100644
--- a/core/java/android/hardware/ISensorService.aidl
+++ b/core/java/android/hardware/ISensorService.aidl
@@ -17,13 +17,13 @@
 
 package android.hardware;
 
-import android.os.ParcelFileDescriptor;
+import android.os.Bundle;
 
 /**
  * {@hide}
  */
 interface ISensorService
 {
-    ParcelFileDescriptor getDataChanel();
+    Bundle getDataChannel();
     boolean enableSensor(IBinder listener, String name, int sensor, int enable);
 }
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index 67df23b..bf945ec 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -18,7 +18,9 @@
 
 import android.content.Context;
 import android.os.Binder;
+import android.os.Bundle;
 import android.os.Looper;
+import android.os.Parcelable;
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.RemoteException;
@@ -280,8 +282,8 @@
         void startLocked(ISensorService service) {
             try {
                 if (mThread == null) {
-                    ParcelFileDescriptor fd = service.getDataChanel();
-                    mThread = new Thread(new SensorThreadRunnable(fd),
+                    Bundle dataChannel = service.getDataChannel();
+                    mThread = new Thread(new SensorThreadRunnable(dataChannel),
                             SensorThread.class.getName());
                     mThread.start();
                 }
@@ -291,10 +293,52 @@
         }
 
         private class SensorThreadRunnable implements Runnable {
-            private ParcelFileDescriptor mSensorDataFd;
-            SensorThreadRunnable(ParcelFileDescriptor fd) {
-                mSensorDataFd = fd;
+            private Bundle mDataChannel;
+            SensorThreadRunnable(Bundle dataChannel) {
+                mDataChannel = dataChannel;
             }
+
+            private boolean open() {
+                if (mDataChannel == null) {
+                    Log.e(TAG, "mDataChannel == NULL, exiting");
+                    synchronized (sListeners) {
+                        mThread = null;
+                    }
+                    return false;
+                }
+
+                // this thread is guaranteed to be unique
+                Parcelable[] pfds = mDataChannel.getParcelableArray("fds");
+                FileDescriptor[] fds;
+                if (pfds != null) {
+                    int length = pfds.length;
+                    fds = new FileDescriptor[length];
+                    for (int i = 0; i < length; i++) {
+                        ParcelFileDescriptor pfd = (ParcelFileDescriptor)pfds[i];
+                        fds[i] = pfd.getFileDescriptor();
+                    }
+                } else {
+                    fds = null;
+                }
+                int[] ints = mDataChannel.getIntArray("ints");
+                sensors_data_open(fds, ints);
+                if (pfds != null) {
+                    try {
+                        // close our copies of the file descriptors,
+                        // since we are just passing these to the JNI code and not using them here.
+                        for (int i = pfds.length - 1; i >= 0; i--) {
+                            ParcelFileDescriptor pfd = (ParcelFileDescriptor)pfds[i];
+                            pfd.close();
+                        }
+                    } catch (IOException e) {
+                        // *shrug*
+                        Log.e(TAG, "IOException: ", e);
+                    }
+                }
+                mDataChannel = null;
+                return true;
+            }
+
             public void run() {
                 //Log.d(TAG, "entering main sensor thread");
                 final float[] values = new float[3];
@@ -302,23 +346,9 @@
                 final long timestamp[] = new long[1];
                 Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY);
 
-                if (mSensorDataFd == null) {
-                    Log.e(TAG, "mSensorDataFd == NULL, exiting");
-                    synchronized (sListeners) {
-                        mThread = null;
-                    }
+                if (!open()) {
                     return;
                 }
-                // this thread is guaranteed to be unique
-                sensors_data_open(mSensorDataFd.getFileDescriptor());
-                try {
-                    mSensorDataFd.close();
-                } catch (IOException e) {
-                    // *shrug*
-                    Log.e(TAG, "IOException: ", e);
-                }
-                mSensorDataFd = null;
-
 
                 while (true) {
                     // wait for an event
@@ -1469,7 +1499,7 @@
     // Used within this module from outside SensorManager, don't make private
     static native int sensors_data_init();
     static native int sensors_data_uninit();
-    static native int sensors_data_open(FileDescriptor fd);
+    static native int sensors_data_open(FileDescriptor[] fds, int[] ints);
     static native int sensors_data_close();
     static native int sensors_data_poll(float[] values, int[] status, long[] timestamp);
 }
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 8a0fd58..358a546 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -69,6 +69,20 @@
      public static final int WIFI_MULTICAST_ENABLED = 7;
 
     /**
+     * A constant indicating an audio turn on timer
+     *
+     * {@hide}
+     */
+    public static final int AUDIO_TURNED_ON = 7;
+
+    /**
+     * A constant indicating a video turn on timer
+     *
+     * {@hide}
+     */
+    public static final int VIDEO_TURNED_ON = 8;
+
+    /**
      * Include all of the data in the stats, including previously saved data.
      */
     public static final int STATS_TOTAL = 0;
@@ -164,7 +178,7 @@
          * @return a time in microseconds
          */
         public abstract long getTotalTimeLocked(long batteryRealtime, int which);
-        
+
         /**
          * Temporary for debugging.
          */
@@ -234,11 +248,17 @@
         public abstract void noteScanWifiLockReleasedLocked();
         public abstract void noteWifiMulticastEnabledLocked();
         public abstract void noteWifiMulticastDisabledLocked();
+        public abstract void noteAudioTurnedOnLocked();
+        public abstract void noteAudioTurnedOffLocked();
+        public abstract void noteVideoTurnedOnLocked();
+        public abstract void noteVideoTurnedOffLocked();
         public abstract long getWifiTurnedOnTime(long batteryRealtime, int which);
         public abstract long getFullWifiLockTime(long batteryRealtime, int which);
         public abstract long getScanWifiLockTime(long batteryRealtime, int which);
         public abstract long getWifiMulticastTime(long batteryRealtime,
                                                   int which);
+        public abstract long getAudioTurnedOnTime(long batteryRealtime, int which);
+        public abstract long getVideoTurnedOnTime(long batteryRealtime, int which);
 
         /**
          * Note that these must match the constants in android.os.LocalPowerManager.
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 101336b..963875d 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -38,6 +38,9 @@
     /** The name of the underlying board, like "goldfish". */
     public static final String BOARD = getString("ro.product.board");
 
+    /** The name of the instruction set (CPU type + ABI convention) of native code. */
+    public static final String CPU_ABI = getString("ro.product.cpu.abi");
+
     /** The manufacturer of the product/hardware. */
     public static final String MANUFACTURER = getString("ro.product.manufacturer");
 
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index b669fa2..a91655f 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -78,6 +78,10 @@
         readFromParcel(parcelledData);
     }
 
+    /* package */ Bundle(Parcel parcelledData, int length) {
+        readFromParcelInner(parcelledData, length);
+    }
+
     /**
      * Constructs a new, empty Bundle that uses a specific ClassLoader for
      * instantiating Parcelable and Serializable objects.
@@ -155,13 +159,14 @@
             return;
         }
 
-        mParcelledData.setDataPosition(0);
-        Bundle b = mParcelledData.readBundleUnpacked(mClassLoader);
-        mMap = b.mMap;
-
-        mHasFds = mParcelledData.hasFileDescriptors();
-        mFdsKnown = true;
-        
+        int N = mParcelledData.readInt();
+        if (N < 0) {
+            return;
+        }
+        if (mMap == null) {
+            mMap = new HashMap<String, Object>();
+        }
+        mParcelledData.readMapInternal(mMap, N, mClassLoader);
         mParcelledData.recycle();
         mParcelledData = null;
     }
@@ -1427,7 +1432,25 @@
      * @param parcel The parcel to copy this bundle to.
      */
     public void writeToParcel(Parcel parcel, int flags) {
-        parcel.writeBundle(this);
+        if (mParcelledData != null) {
+            int length = mParcelledData.dataSize();
+            parcel.writeInt(length);
+            parcel.writeInt(0x4C444E42); // 'B' 'N' 'D' 'L'
+            parcel.appendFrom(mParcelledData, 0, length);
+        } else {
+            parcel.writeInt(-1); // dummy, will hold length
+            parcel.writeInt(0x4C444E42); // 'B' 'N' 'D' 'L'
+
+            int oldPos = parcel.dataPosition();
+            parcel.writeMapInternal(mMap);
+            int newPos = parcel.dataPosition();
+
+            // Backpatch length
+            parcel.setDataPosition(oldPos - 8);
+            int length = newPos - oldPos;
+            parcel.writeInt(length);
+            parcel.setDataPosition(newPos);
+        }
     }
 
     /**
@@ -1436,8 +1459,33 @@
      * @param parcel The parcel to overwrite this bundle from.
      */
     public void readFromParcel(Parcel parcel) {
-        mParcelledData = parcel;
-        mHasFds = mParcelledData.hasFileDescriptors();
+        int length = parcel.readInt();
+        if (length < 0) {
+            throw new RuntimeException("Bad length in parcel: " + length);
+        }
+        readFromParcelInner(parcel, length);
+    }
+
+    void readFromParcelInner(Parcel parcel, int length) {
+        int magic = parcel.readInt();
+        if (magic != 0x4C444E42) {
+            //noinspection ThrowableInstanceNeverThrown
+            String st = Log.getStackTraceString(new RuntimeException());
+            Log.e("Bundle", "readBundle: bad magic number");
+            Log.e("Bundle", "readBundle: trace = " + st);
+        }
+
+        // Advance within this Parcel
+        int offset = parcel.dataPosition();
+        parcel.setDataPosition(offset + length);
+
+        Parcel p = Parcel.obtain();
+        p.setDataPosition(0);
+        p.appendFrom(parcel, offset, length);
+        p.setDataPosition(0);
+        
+        mParcelledData = p;
+        mHasFds = p.hasFileDescriptors();
         mFdsKnown = true;
     }
 
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 9a71f6e..6cfccee 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -457,7 +457,7 @@
      * Flatten a Map into the parcel at the current dataPosition(),
      * growing dataCapacity() if needed.  The Map keys must be String objects.
      */
-    private void writeMapInternal(Map<String,Object> val) {
+    /* package */ void writeMapInternal(Map<String,Object> val) {
         if (val == null) {
             writeInt(-1);
             return;
@@ -480,23 +480,7 @@
             return;
         }
 
-        if (val.mParcelledData != null) {
-            int length = val.mParcelledData.dataSize();
-            appendFrom(val.mParcelledData, 0, length);
-        } else {
-            writeInt(-1); // dummy, will hold length
-            int oldPos = dataPosition();
-            writeInt(0x4C444E42); // 'B' 'N' 'D' 'L'
-
-            writeMapInternal(val.mMap);
-            int newPos = dataPosition();
-
-            // Backpatch length
-            setDataPosition(oldPos - 4);
-            int length = newPos - oldPos;
-            writeInt(length);
-            setDataPosition(newPos);
-        }
+        val.writeToParcel(this, 0);
     }
 
     /**
@@ -1352,27 +1336,12 @@
      * Returns null if the previously written Bundle object was null.
      */
     public final Bundle readBundle(ClassLoader loader) {
-        int offset = dataPosition();
         int length = readInt();
         if (length < 0) {
             return null;
         }
-        int magic = readInt();
-        if (magic != 0x4C444E42) {
-            //noinspection ThrowableInstanceNeverThrown
-            String st = Log.getStackTraceString(new RuntimeException());
-            Log.e("Bundle", "readBundle: bad magic number");
-            Log.e("Bundle", "readBundle: trace = " + st);
-        }
-
-        // Advance within this Parcel
-        setDataPosition(offset + length + 4);
-
-        Parcel p = new Parcel(0);
-        p.setDataPosition(0);
-        p.appendFrom(this, offset, length + 4);
-        p.setDataPosition(0);
-        final Bundle bundle = new Bundle(p);
+        
+        final Bundle bundle = new Bundle(this, length);
         if (loader != null) {
             bundle.setClassLoader(loader);
         }
@@ -1380,33 +1349,6 @@
     }
 
     /**
-     * Read and return a new Bundle object from the parcel at the current
-     * dataPosition().  Returns null if the previously written Bundle object was
-     * null.  The returned bundle will have its contents fully unpacked using
-     * the given ClassLoader.
-     */
-    /* package */ Bundle readBundleUnpacked(ClassLoader loader) {
-        int length = readInt();
-        if (length == -1) {
-            return null;
-        }
-        int magic = readInt();
-        if (magic != 0x4C444E42) {
-            //noinspection ThrowableInstanceNeverThrown
-            String st = Log.getStackTraceString(new RuntimeException());
-            Log.e("Bundle", "readBundleUnpacked: bad magic number");
-            Log.e("Bundle", "readBundleUnpacked: trace = " + st);
-        }
-        Bundle m = new Bundle(loader);
-        int N = readInt();
-        if (N < 0) {
-            return null;
-        }
-        readMapInternal(m.mMap, N, loader);
-        return m;
-    }
-
-    /**
      * Read and return a byte[] object from the parcel.
      */
     public final native byte[] createByteArray();
@@ -1998,7 +1940,7 @@
     private native void init(int obj);
     private native void destroy();
 
-    private void readMapInternal(Map outVal, int N,
+    /* package */ void readMapInternal(Map outVal, int N,
         ClassLoader loader) {
         while (N > 0) {
             Object key = readValue(loader);
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index b6f96c4..51d1951 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -737,7 +737,7 @@
                     name.endsWith(", a") || name.endsWith(",a")) {
                     name = name.substring(0, name.lastIndexOf(','));
                 }
-                name = name.replaceAll("[\\[\\]\\(\\)'.,?!]", "").trim();
+                name = name.replaceAll("[\\[\\]\\(\\)\"'.,?!]", "").trim();
                 if (name.length() > 0) {
                     // Insert a separator between the characters to avoid
                     // matches on a partial character. If we ever change
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 49e4e4c..e70c94c 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -101,6 +101,8 @@
     static final int KEEP_SCREEN_ON_MSG = 1;
     static final int GET_NEW_SURFACE_MSG = 2;
     
+    int mWindowType = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
+    
     boolean mIsCreating = false;
 
     final Handler mHandler = new Handler() {
@@ -286,6 +288,15 @@
         super.dispatchDraw(canvas);
     }
 
+    /**
+     * Hack to allow special layering of windows.  The type is one of the
+     * types in WindowManager.LayoutParams.  This is a hack so:
+     * @hide
+     */
+    public void setWindowType(int type) {
+        mWindowType = type;
+    }
+    
     private void updateWindow(boolean force) {
         if (!mHaveFrame) {
             return;
@@ -343,7 +354,7 @@
 
                 if (mWindow == null) {
                     mWindow = new MyWindow(this);
-                    mLayout.type = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
+                    mLayout.type = mWindowType;
                     mLayout.gravity = Gravity.LEFT|Gravity.TOP;
                     mSession.add(mWindow, mLayout,
                             mVisible ? VISIBLE : GONE, mContentInsets);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 1f72eea..bcb97ed 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -538,21 +538,48 @@
  * take care of redrawing the appropriate views until the animation completes.
  * </p>
  *
+ * @attr ref android.R.styleable#View_background
+ * @attr ref android.R.styleable#View_clickable
+ * @attr ref android.R.styleable#View_contentDescription
+ * @attr ref android.R.styleable#View_drawingCacheQuality
+ * @attr ref android.R.styleable#View_duplicateParentState
+ * @attr ref android.R.styleable#View_id
+ * @attr ref android.R.styleable#View_fadingEdge
+ * @attr ref android.R.styleable#View_fadingEdgeLength
  * @attr ref android.R.styleable#View_fitsSystemWindows
+ * @attr ref android.R.styleable#View_isScrollContainer
+ * @attr ref android.R.styleable#View_focusable
+ * @attr ref android.R.styleable#View_focusableInTouchMode
+ * @attr ref android.R.styleable#View_hapticFeedbackEnabled
+ * @attr ref android.R.styleable#View_keepScreenOn
+ * @attr ref android.R.styleable#View_longClickable
+ * @attr ref android.R.styleable#View_minHeight
+ * @attr ref android.R.styleable#View_minWidth
  * @attr ref android.R.styleable#View_nextFocusDown
  * @attr ref android.R.styleable#View_nextFocusLeft
  * @attr ref android.R.styleable#View_nextFocusRight
  * @attr ref android.R.styleable#View_nextFocusUp
+ * @attr ref android.R.styleable#View_onClick
+ * @attr ref android.R.styleable#View_padding
+ * @attr ref android.R.styleable#View_paddingBottom
+ * @attr ref android.R.styleable#View_paddingLeft
+ * @attr ref android.R.styleable#View_paddingRight
+ * @attr ref android.R.styleable#View_paddingTop
+ * @attr ref android.R.styleable#View_saveEnabled
  * @attr ref android.R.styleable#View_scrollX
  * @attr ref android.R.styleable#View_scrollY
+ * @attr ref android.R.styleable#View_scrollbarSize
+ * @attr ref android.R.styleable#View_scrollbarStyle
+ * @attr ref android.R.styleable#View_scrollbars
  * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
  * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
- * @attr ref android.R.styleable#View_scrollbarSize
- * @attr ref android.R.styleable#View_scrollbars
  * @attr ref android.R.styleable#View_scrollbarThumbVertical
  * @attr ref android.R.styleable#View_scrollbarTrackVertical
  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
+ * @attr ref android.R.styleable#View_soundEffectsEnabled
+ * @attr ref android.R.styleable#View_tag
+ * @attr ref android.R.styleable#View_visibility
  *
  * @see android.view.ViewGroup
  */
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index bf04dcd..8b0629c 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -53,6 +53,15 @@
  * <p>
  * Also see {@link LayoutParams} for layout attributes.
  * </p>
+ *
+ * @attr ref android.R.styleable#ViewGroup_clipChildren
+ * @attr ref android.R.styleable#ViewGroup_clipToPadding
+ * @attr ref android.R.styleable#ViewGroup_layoutAnimation
+ * @attr ref android.R.styleable#ViewGroup_animationCache
+ * @attr ref android.R.styleable#ViewGroup_persistentDrawingCache
+ * @attr ref android.R.styleable#ViewGroup_alwaysDrawnWithCache
+ * @attr ref android.R.styleable#ViewGroup_addStatesFromChildren
+ * @attr ref android.R.styleable#ViewGroup_descendantFocusability
  */
 public abstract class ViewGroup extends View implements ViewParent, ViewManager {
     private static final boolean DBG = false;
@@ -2342,7 +2351,8 @@
             final boolean drawAnimation = (child.mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION;
 
             // Check whether the child that requests the invalidate is fully opaque
-            final boolean isOpaque = child.isOpaque();
+            final boolean isOpaque = child.isOpaque() && !drawAnimation &&
+                    child.getAnimation() != null;
             // Mark the child as dirty, using the appropriate flag
             // Make sure we do not set both flags at the same time
             final int opaqueFlag = isOpaque ? DIRTY_OPAQUE : DIRTY;
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index b0e738c..d7457a0 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -376,8 +376,14 @@
                     String title;
                     if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA) {
                         title="Media";
+                    } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY) {
+                        title="MediaOvr";
                     } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
                         title="Panel";
+                    } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL) {
+                        title="SubPanel";
+                    } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG) {
+                        title="AtchDlg";
                     } else {
                         title=Integer.toString(wp.type);
                     }
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 72ef0ad..ec2069c 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -210,6 +210,15 @@
         public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3;
         
         /**
+         * Window type: window for showing overlays on top of media windows.
+         * These windows are displayed between TYPE_APPLICATION_MEDIA and the
+         * application window.  They should be translucent to be useful.  This
+         * is a big ugly hack so:
+         * @hide
+         */
+        public static final int TYPE_APPLICATION_MEDIA_OVERLAY  = FIRST_SUB_WINDOW+4;
+    
+        /**
          * End of types of sub-windows.
          */
         public static final int LAST_SUB_WINDOW         = 1999;
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 6229da7..08ca209 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -145,6 +145,17 @@
     }
 
     /**
+     * Load a url with "POST" method from the network into the main frame.
+     * @param url The url to load.
+     * @param data The data for POST request.
+     */
+    public void postUrl(String url, byte[] data) {
+        mLoadInitFromJava = true;
+        nativePostUrl(url, data);
+        mLoadInitFromJava = false;
+    }
+
+    /**
      * Load the content as if it was loaded by the provided base URL. The
      * failUrl is used as the history entry for the load data. If null or
      * an empty string is passed for the failUrl, then no history entry is
@@ -754,6 +765,8 @@
      */
     private native void nativeLoadUrl(String url);
 
+    private native void nativePostUrl(String url, byte[] postData);
+
     private native void nativeLoadData(String baseUrl, String data,
             String mimeType, String encoding, String failUrl);
 
diff --git a/core/java/android/webkit/SslErrorHandler.java b/core/java/android/webkit/SslErrorHandler.java
index 5f84bbe..617a3145 100644
--- a/core/java/android/webkit/SslErrorHandler.java
+++ b/core/java/android/webkit/SslErrorHandler.java
@@ -227,7 +227,7 @@
                 boolean hasKey = mSslPrefTable.containsKey(host);
                 if (!hasKey ||
                     primary > mSslPrefTable.getInt(host)) {
-                    mSslPrefTable.putInt(host, new Integer(primary));
+                    mSslPrefTable.putInt(host, primary);
                 }
             }
             loader.handleSslErrorResponse(proceed);
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 93ffcdb..e735292 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -127,7 +127,7 @@
     private String          mSerifFontFamily = "serif";
     private String          mCursiveFontFamily = "cursive";
     private String          mFantasyFontFamily = "fantasy";
-    private String          mDefaultTextEncoding = "Latin-1";
+    private String          mDefaultTextEncoding;
     private String          mUserAgent;
     private boolean         mUseDefaultUserAgent;
     private String          mAcceptLanguage;
@@ -248,6 +248,8 @@
     WebSettings(Context context) {   
         mEventHandler = new EventHandler();
         mContext = context;
+        mDefaultTextEncoding = context.getString(com.android.internal.
+                                                 R.string.default_text_encoding);
 
         if (sLockForLocaleSettings == null) {
             sLockForLocaleSettings = new Object();
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 82f8a3d..8fff644 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -210,7 +210,7 @@
     static final boolean DEBUG = false;
     static final boolean LOGV_ENABLED = DEBUG;
 
-    private class ExtendedZoomControls extends FrameLayout {
+    private static class ExtendedZoomControls extends FrameLayout {
         public ExtendedZoomControls(Context context, AttributeSet attrs) {
             super(context, attrs);
             LayoutInflater inflater = (LayoutInflater)
@@ -564,7 +564,8 @@
         public void onNewPicture(WebView view, Picture picture);
     }
 
-    public class HitTestResult {
+    // FIXME: Want to make this public, but need to change the API file.
+    public /*static*/ class HitTestResult {
         /**
          * Default HitTestResult, where the target is unknown
          */
@@ -1215,6 +1216,29 @@
     }
 
     /**
+     * Load the url with postData using "POST" method into the WebView. If url
+     * is not a network url, it will be loaded with {link
+     * {@link #loadUrl(String)} instead.
+     * 
+     * @param url The url of the resource to load.
+     * @param postData The data will be passed to "POST" request.
+     * 
+     * @hide pending API solidification
+     */
+    public void postUrl(String url, byte[] postData) {
+        if (URLUtil.isNetworkUrl(url)) {
+            switchOutDrawHistory();
+            HashMap arg = new HashMap();
+            arg.put("url", url);
+            arg.put("data", postData);
+            mWebViewCore.sendMessage(EventHub.POST_URL, arg);
+            clearTextEntry();
+        } else {
+            loadUrl(url);
+        }
+    }
+
+    /**
      * Load the given data into the WebView. This will load the data into
      * WebView using the data: scheme. Content loaded through this mechanism
      * does not have the ability to load content from the network.
@@ -2859,7 +2883,7 @@
     /**
      *  Class representing the node which is focused.
      */
-    private class FocusNode {
+    private static class FocusNode {
         public FocusNode() {
             mBounds = new Rect();
         }
@@ -4568,8 +4592,8 @@
         HashMap arg = new HashMap();
         arg.put("focusData", new WebViewCore.FocusData(mFocusData));
         arg.put("replace", replace);
-        arg.put("start", new Integer(newStart));
-        arg.put("end", new Integer(newEnd));
+        arg.put("start", Integer.valueOf(newStart));
+        arg.put("end", Integer.valueOf(newEnd));
         mTextGeneration++;
         mWebViewCore.sendMessage(EventHub.REPLACE_TEXT, oldStart, oldEnd, arg);
     }
@@ -4888,10 +4912,6 @@
 
     // Class used to use a dropdown for a <select> element
     private class InvokeListBox implements Runnable {
-        // Strings for the labels in the listbox.
-        private String[]    mArray;
-        // Array representing whether each item is enabled.
-        private boolean[]   mEnableArray;
         // Whether the listbox allows multiple selection.
         private boolean     mMultiple;
         // Passed in to a list with multiple selection to tell
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 4416f1e..e4d08cf 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -580,7 +580,7 @@
             "GET_SELECTION", // = 129;
             "WEBKIT_DRAW", // = 130;
             "SYNC_SCROLL", // = 131;
-            "", // = 132;
+            "POST_URL", // = 132;
             "SPLIT_PICTURE_SET", // = 133;
             "CLEAR_CONTENT", // = 134;
             "SET_FINAL_FOCUS", // = 135;
@@ -627,6 +627,7 @@
         static final int GET_SELECTION = 129;
         static final int WEBKIT_DRAW = 130;
         static final int SYNC_SCROLL = 131;
+        static final int POST_URL = 132;
         static final int SPLIT_PICTURE_SET = 133;
         static final int CLEAR_CONTENT = 134;
         
@@ -714,6 +715,13 @@
                             loadUrl((String) msg.obj);
                             break;
 
+                        case POST_URL: {
+                            HashMap param = (HashMap) msg.obj;
+                            String url = (String) param.get("url");
+                            byte[] data = (byte[]) param.get("data");
+                            mBrowserFrame.postUrl(url, data);
+                            break;
+                        }
                         case LOAD_DATA:
                             HashMap loadParams = (HashMap) msg.obj;
                             String baseUrl = (String) loadParams.get("baseUrl");
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 1ca59b2..e896d58 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -41,12 +41,17 @@
 import android.view.ViewDebug;
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
+import android.view.KeyCharacterMap;
 import android.view.inputmethod.BaseInputConnection;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputConnectionWrapper;
 import android.view.inputmethod.InputMethodManager;
 import android.view.ContextMenu.ContextMenuInfo;
+import android.gesture.GestureOverlayView;
+import android.gesture.Gesture;
+import android.gesture.LetterRecognizer;
+import android.gesture.Prediction;
 
 import com.android.internal.R;
 
@@ -54,7 +59,9 @@
 import java.util.List;
 
 /**
- * Common code shared between ListView and GridView
+ * Base class that can be used to implement virtualized lists of items. A list does
+ * not have a spatial definition here. For instance, subclases of this class can
+ * display the content of the list in a grid, in a carousel, as stack, etc.
  *
  * @attr ref android.R.styleable#AbsListView_listSelector
  * @attr ref android.R.styleable#AbsListView_drawSelectorOnTop
@@ -65,6 +72,7 @@
  * @attr ref android.R.styleable#AbsListView_cacheColorHint
  * @attr ref android.R.styleable#AbsListView_fastScrollEnabled
  * @attr ref android.R.styleable#AbsListView_smoothScrollbar
+ * @attr ref android.R.styleable#AbsListView_gestures
  */
 public abstract class AbsListView extends AdapterView<ListAdapter> implements TextWatcher,
         ViewTreeObserver.OnGlobalLayoutListener, Filter.FilterListener,
@@ -93,6 +101,31 @@
     public static final int TRANSCRIPT_MODE_ALWAYS_SCROLL = 2;
 
     /**
+     * Disables gestures.
+     *
+     * @see #setGestures(int)
+     * @see #GESTURES_JUMP
+     * @see #GESTURES_FILTER
+     */
+    public static final int GESTURES_NONE = 0;
+    /**
+     * When a letter gesture is recognized the list jumps to a matching position.
+     *
+     * @see #setGestures(int)
+     * @see #GESTURES_NONE
+     * @see #GESTURES_FILTER
+     */
+    public static final int GESTURES_JUMP = 1;
+    /**
+     * When a letter gesture is recognized the letter is added to the filter.
+     *
+     * @see #setGestures(int)
+     * @see #GESTURES_NONE
+     * @see #GESTURES_JUMP
+     */
+    public static final int GESTURES_FILTER = 2;
+
+    /**
      * Indicates that we are not in the middle of a touch gesture
      */
     static final int TOUCH_MODE_REST = -1;
@@ -427,8 +460,22 @@
      */
     private FastScroller mFastScroller;
 
-    private int mTouchSlop;
+    /**
+     * Indicates the type of gestures to use: GESTURES_NONE, GESTURES_FILTER or GESTURES_NONE
+     */
+    private int mGestures;
 
+    // Used to implement the gestures overlay
+    private GestureOverlayView mGesturesOverlay;
+    private PopupWindow mGesturesPopup;
+    private ViewTreeObserver.OnGlobalLayoutListener mGesturesLayoutListener;
+    private boolean mGlobalLayoutListenerAddedGestures;
+    private boolean mInstallGesturesOverlay;
+    private boolean mPreviousGesturing;
+
+    private boolean mGlobalLayoutListenerAddedFilter;
+
+    private int mTouchSlop;
     private float mDensityScale;
 
     private InputConnection mDefInputConnection;
@@ -535,10 +582,201 @@
 
         boolean smoothScrollbar = a.getBoolean(R.styleable.AbsListView_smoothScrollbar, true);
         setSmoothScrollbarEnabled(smoothScrollbar);
-        
+
+        int defaultGestures = GESTURES_NONE;
+        if (useTextFilter) {
+            defaultGestures = GESTURES_FILTER;
+        } else if (enableFastScroll) {
+            defaultGestures = GESTURES_JUMP;
+        }
+        int gestures = a.getInt(R.styleable.AbsListView_gestures, defaultGestures);
+        setGestures(gestures);
+
         a.recycle();
     }
 
+    private void initAbsListView() {
+        // Setting focusable in touch mode will set the focusable property to true
+        setFocusableInTouchMode(true);
+        setWillNotDraw(false);
+        setAlwaysDrawnWithCacheEnabled(false);
+        setScrollingCacheEnabled(true);
+
+        mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
+        mDensityScale = getContext().getResources().getDisplayMetrics().density;
+    }
+    
+    /**
+     * <p>Sets the type of gestures to use with this list. When gestures are enabled,
+     * that is if the <code>gestures</code> parameter is not {@link #GESTURES_NONE},
+     * the user can draw characters on top of this view. When a character is
+     * recognized and matches a known character, the list will either:</p>
+     * <ul>
+     * <li>Jump to the appropriate position ({@link #GESTURES_JUMP})</li>
+     * <li>Add the character to the current filter ({@link #GESTURES_FILTER})</li>
+     * </ul>
+     * <p>Using {@link #GESTURES_JUMP} requires {@link #isFastScrollEnabled()} to
+     * be true. Using {@link #GESTURES_FILTER} requires {@link #isTextFilterEnabled()}
+     * to be true.</p>
+     *
+     * @param gestures The type of gestures to enable for this list:
+     *        {@link #GESTURES_NONE}, {@link #GESTURES_JUMP} or {@link #GESTURES_FILTER}
+     *
+     * @see #GESTURES_NONE
+     * @see #GESTURES_JUMP
+     * @see #GESTURES_FILTER
+     * @see #getGestures()
+     */
+    public void setGestures(int gestures) {
+        switch (gestures) {
+            case GESTURES_JUMP:
+                if (!mFastScrollEnabled) {
+                    throw new IllegalStateException("Jump gestures can only be used with "
+                            + "fast scroll enabled");
+                }
+                break;
+            case GESTURES_FILTER:
+                if (!mTextFilterEnabled) {
+                    throw new IllegalStateException("Filter gestures can only be used with "
+                            + "text filtering enabled");
+                }
+                break;
+        }
+
+        final int oldGestures = mGestures;
+        mGestures = gestures;
+
+        // Install overlay later
+        if (oldGestures == GESTURES_NONE && gestures != GESTURES_NONE) {
+            mInstallGesturesOverlay = true;
+        // Uninstall overlay
+        } else if (oldGestures != GESTURES_NONE && gestures == GESTURES_NONE) {
+            uninstallGesturesOverlay();
+        }
+    }
+
+    /**
+     * Indicates what gestures are enabled on this view.
+     *
+     * @return {@link #GESTURES_NONE}, {@link #GESTURES_JUMP} or {@link #GESTURES_FILTER}
+     *
+     * @see #GESTURES_NONE
+     * @see #GESTURES_JUMP
+     * @see #GESTURES_FILTER
+     * @see #setGestures(int) 
+     */
+    @ViewDebug.ExportedProperty(mapping = {
+        @ViewDebug.IntToString(from = GESTURES_NONE, to = "NONE"),
+        @ViewDebug.IntToString(from = GESTURES_JUMP, to = "JUMP"),
+        @ViewDebug.IntToString(from = GESTURES_FILTER, to = "FILTER")
+    })
+    public int getGestures() {
+        return mGestures;
+    }
+
+    private void dismissGesturesPopup() {
+        if (mGesturesPopup != null) {
+            mGesturesPopup.dismiss();
+        }
+    }
+
+    private void showGesturesPopup() {
+        // Make sure we have a window before showing the popup
+        if (getWindowVisibility() == View.VISIBLE) {
+            installGesturesOverlay();
+            positionGesturesPopup();
+        }
+    }
+
+    private void positionGesturesPopup() {
+        final int[] xy = new int[2];
+        getLocationOnScreen(xy);
+        if (!mGesturesPopup.isShowing()) {
+            mGesturesPopup.showAtLocation(this, Gravity.LEFT | Gravity.TOP, xy[0], xy[1]);
+        } else {
+            mGesturesPopup.update(xy[0], xy[1], -1, -1);
+        }
+    }
+
+    private void installGesturesOverlay() {
+        mInstallGesturesOverlay = false;
+
+        if (mGesturesPopup == null) {
+            final Context c = getContext();
+            final LayoutInflater layoutInflater = (LayoutInflater)
+                    c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+            mGesturesOverlay = (GestureOverlayView)
+                    layoutInflater.inflate(R.layout.list_gestures_overlay, null);
+
+            final PopupWindow p = new PopupWindow(c);
+            p.setFocusable(false);
+            p.setTouchable(false);
+            p.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
+            p.setContentView(mGesturesOverlay);
+            p.setWidth(getWidth());
+            p.setHeight(getHeight());
+            p.setBackgroundDrawable(null);
+
+            if (mGesturesLayoutListener == null) {
+                mGesturesLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
+                    public void onGlobalLayout() {
+                        if (isShown()) {
+                            showGesturesPopup();
+                        } else if (mGesturesPopup.isShowing()) {
+                            dismissGesturesPopup();
+                        }
+                    }
+                };
+            }
+            getViewTreeObserver().addOnGlobalLayoutListener(mGesturesLayoutListener);
+            mGlobalLayoutListenerAddedGestures = true;
+
+            mGesturesPopup = p;
+
+            mGesturesOverlay.removeAllOnGestureListeners();
+            mGesturesOverlay.setGestureStrokeType(GestureOverlayView.GESTURE_STROKE_TYPE_MULTIPLE);
+            mGesturesOverlay.addOnGesturePerformedListener(new GesturesProcessor());
+
+            mPreviousGesturing = false;            
+        }
+    }
+
+    private void uninstallGesturesOverlay() {
+        dismissGesturesPopup();
+        mGesturesPopup = null;
+        if (mGesturesLayoutListener != null) {
+            getViewTreeObserver().removeGlobalOnLayoutListener(mGesturesLayoutListener);
+        }
+    }
+
+    @Override
+    public boolean dispatchTouchEvent(MotionEvent ev) {
+        if (mGestures != GESTURES_NONE) {
+            if (ev.getAction() != MotionEvent.ACTION_DOWN || mFastScroller == null ||
+                    !mFastScroller.isPointInside(ev.getX(), ev.getY())) {
+
+                if (mGesturesPopup.isShowing()) {
+                    mGesturesOverlay.dispatchTouchEvent(ev);
+
+                    final boolean isGesturing = mGesturesOverlay.isGesturing();
+
+                    if (!isGesturing) {
+                        mPreviousGesturing = isGesturing;
+                        return super.dispatchTouchEvent(ev);
+                    } else if (!mPreviousGesturing){
+                        mPreviousGesturing = isGesturing;
+                        final MotionEvent event = MotionEvent.obtain(ev);
+                        event.setAction(MotionEvent.ACTION_CANCEL);
+                        super.dispatchTouchEvent(event);
+                        return true;
+                    }
+                }
+            }
+        }
+
+        return super.dispatchTouchEvent(ev);
+    }
+
     /**
      * Enables fast scrolling by letting the user quickly scroll through lists by 
      * dragging the fast scroll thumb. The adapter attached to the list may want 
@@ -712,17 +950,6 @@
         }
     }
 
-    private void initAbsListView() {
-        // Setting focusable in touch mode will set the focusable property to true
-        setFocusableInTouchMode(true);
-        setWillNotDraw(false);
-        setAlwaysDrawnWithCacheEnabled(false);
-        setScrollingCacheEnabled(true);
-
-        mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
-        mDensityScale = getContext().getResources().getDisplayMetrics().density;
-    }
-
     private void useDefaultSelector() {
         setSelector(getResources().getDrawable(
                 com.android.internal.R.drawable.list_selector_background));
@@ -908,11 +1135,8 @@
     }
 
     private boolean acceptFilter() {
-        if (!mTextFilterEnabled || !(getAdapter() instanceof Filterable) ||
-                ((Filterable) getAdapter()).getFilter() == null) {
-            return false;
-        }
-        return true;
+        return mTextFilterEnabled && getAdapter() instanceof Filterable &&
+                ((Filterable) getAdapter()).getFilter() != null;
     }
 
     /**
@@ -1096,6 +1320,10 @@
         listPadding.bottom = mSelectionBottomPadding + mPaddingBottom;
     }
 
+    /**
+     * Subclasses should NOT override this method but
+     *  {@link #layoutChildren()} instead.
+     */
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         super.onLayout(changed, l, t, r, b);
@@ -1111,17 +1339,27 @@
     protected boolean setFrame(int left, int top, int right, int bottom) {
         final boolean changed = super.setFrame(left, top, right, bottom);
 
-        // Reposition the popup when the frame has changed. This includes
-        // translating the widget, not just changing its dimension. The
-        // filter popup needs to follow the widget.
-        if (mFiltered && changed && getWindowVisibility() == View.VISIBLE && mPopup != null &&
-                mPopup.isShowing()) {
-            positionPopup();
+        if (changed) {
+            // Reposition the popup when the frame has changed. This includes
+            // translating the widget, not just changing its dimension. The
+            // filter popup needs to follow the widget.
+            final boolean visible = getWindowVisibility() == View.VISIBLE;
+            if (mFiltered && visible && mPopup != null && mPopup.isShowing()) {
+                positionPopup();
+            }
+
+            if (mGestures != GESTURES_NONE && visible && mGesturesPopup != null &&
+                    mGesturesPopup.isShowing()) {
+                positionGesturesPopup();
+            }
         }
 
         return changed;
     }
 
+    /**
+     * Subclasses must override this method to layout their children.
+     */
     protected void layoutChildren() {
     }
 
@@ -1324,9 +1562,17 @@
             mDataChanged = true;
             rememberSyncState();
         }
+
         if (mFastScroller != null) {
             mFastScroller.onSizeChanged(w, h, oldw, oldh);
         }
+
+        if (mInstallGesturesOverlay) {
+            installGesturesOverlay();
+            positionGesturesPopup();
+        } else if (mGesturesPopup != null) {
+            mGesturesPopup.update(w, h);
+        }
     }
 
     /**
@@ -1510,6 +1756,13 @@
         final ViewTreeObserver treeObserver = getViewTreeObserver();
         if (treeObserver != null) {
             treeObserver.addOnTouchModeChangeListener(this);
+            if (mTextFilterEnabled && mPopup != null && !mGlobalLayoutListenerAddedFilter) {
+                treeObserver.addOnGlobalLayoutListener(this);
+            }
+            if (mGestures != GESTURES_NONE && mGesturesPopup != null &&
+                    !mGlobalLayoutListenerAddedGestures) {
+                treeObserver.addOnGlobalLayoutListener(mGesturesLayoutListener);
+            }
         }
     }
 
@@ -1520,6 +1773,14 @@
         final ViewTreeObserver treeObserver = getViewTreeObserver();
         if (treeObserver != null) {
             treeObserver.removeOnTouchModeChangeListener(this);
+            if (mTextFilterEnabled && mPopup != null) {
+                treeObserver.removeGlobalOnLayoutListener(this);
+                mGlobalLayoutListenerAddedFilter = false;
+            }
+            if (mGesturesLayoutListener != null && mGesturesPopup != null) {
+                mGlobalLayoutListenerAddedGestures = false;
+                treeObserver.removeGlobalOnLayoutListener(mGesturesLayoutListener);
+            }
         }
     }
 
@@ -1534,6 +1795,7 @@
             removeCallbacks(mFlingRunnable);
             // Always hide the type filter
             dismissPopup();
+            dismissGesturesPopup();
 
             if (touchMode == TOUCH_MODE_OFF) {
                 // Remember the last selected element
@@ -1544,6 +1806,9 @@
                 // Show the type filter only if a filter is in effect
                 showPopup();
             }
+            if (mGestures != GESTURES_NONE) {
+                showGesturesPopup();
+            }
 
             // If we changed touch mode since the last time we had focus
             if (touchMode != mLastTouchMode && mLastTouchMode != TOUCH_MODE_UNKNOWN) {
@@ -1664,6 +1929,8 @@
             final int longPressPosition, final long longPressId) {
         boolean handled = false;
 
+        dismissGesturesPopup();
+        
         if (mOnItemLongClickListener != null) {
             handled = mOnItemLongClickListener.onItemLongClick(AbsListView.this, child,
                     longPressPosition, longPressId);
@@ -1867,13 +2134,13 @@
 
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
-        
         if (mFastScroller != null) {
             boolean intercepted = mFastScroller.onTouchEvent(ev);
             if (intercepted) {
                 return true;
             }            
         }
+
         final int action = ev.getAction();
         final int x = (int) ev.getX();
         final int y = (int) ev.getY();
@@ -2775,7 +3042,7 @@
     /**
      * Removes the filter window
      */
-    void dismissPopup() {
+    private void dismissPopup() {
         if (mPopup != null) {
             mPopup.dismiss();
         }
@@ -3017,6 +3284,7 @@
             p.setBackgroundDrawable(null);
             mPopup = p;
             getViewTreeObserver().addOnGlobalLayoutListener(this);
+            mGlobalLayoutListenerAddedFilter = true;
         }
         if (animateEntrance) {
             mPopup.setAnimationStyle(com.android.internal.R.style.Animation_TypingFilter);
@@ -3583,4 +3851,76 @@
             }
         }
     }
+
+    private class GesturesProcessor implements GestureOverlayView.OnGesturePerformedListener {
+
+        private static final double SCORE_THRESHOLD = 0.1;
+
+        private LetterRecognizer mRecognizer;
+        private ArrayList<Prediction> mPredictions;
+        private final KeyCharacterMap mKeyMap;
+        private final char[] mHolder;
+
+        GesturesProcessor() {
+            mRecognizer = LetterRecognizer.getLetterRecognizer(getContext(),
+                    LetterRecognizer.RECOGNIZER_LATIN_LOWERCASE);
+            if (mGestures == GESTURES_FILTER) {
+                mKeyMap = KeyCharacterMap.load(KeyCharacterMap.BUILT_IN_KEYBOARD);
+                mHolder = new char[1];
+            } else {
+                mKeyMap = null;
+                mHolder = null;
+            }
+        }
+
+        public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
+            mPredictions = mRecognizer.recognize(gesture, mPredictions);
+            if (!mPredictions.isEmpty()) {
+                final Prediction prediction = mPredictions.get(0);
+                if (prediction.score > SCORE_THRESHOLD) {
+                    switch (mGestures) {
+                        case GESTURES_JUMP:
+                            processJump(prediction);
+                            break;
+                        case GESTURES_FILTER:
+                            processFilter(prediction);
+                            break;
+                    }
+                }
+            }
+        }
+
+        private void processJump(Prediction prediction) {
+            final Object[] sections = mFastScroller.getSections();
+            if (sections != null) {
+                final String name = prediction.name;
+                final int count = sections.length;
+
+                int index = -1;
+                for (int i = 0; i < count; i++) {
+                    if (name.equalsIgnoreCase((String) sections[i])) {
+                        index = i;
+                        break;
+                    }
+                }
+
+                if (index != -1) {
+                    final SectionIndexer indexer = mFastScroller.getSectionIndexer();
+                    final int position = indexer.getPositionForSection(index);
+                    setSelection(position);
+                }
+            }
+        }
+
+        private void processFilter(Prediction prediction) {
+            mHolder[0] = prediction.name.charAt(0);
+            final KeyEvent[] events = mKeyMap.getEvents(mHolder);
+            if (events != null) {
+                for (KeyEvent event : events) {
+                    sendToTextFilter(event.getKeyCode(), event.getRepeatCount(),
+                            event);
+                }
+            }
+        }
+    }
 }
diff --git a/core/java/android/widget/ExpandableListView.java b/core/java/android/widget/ExpandableListView.java
index 0fc8f49..5360621 100644
--- a/core/java/android/widget/ExpandableListView.java
+++ b/core/java/android/widget/ExpandableListView.java
@@ -1083,6 +1083,11 @@
 
     @Override
     public void onRestoreInstanceState(Parcelable state) {
+        if (!(state instanceof SavedState)) {
+            super.onRestoreInstanceState(state);
+            return;
+        }
+
         SavedState ss = (SavedState) state;
         super.onRestoreInstanceState(ss.getSuperState());
         
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index 3368477..cd965fc6 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -134,7 +134,7 @@
         
         mScrollCompleted = true;
 
-        getSections();
+        getSectionsFromIndexer();
         
         mOverlayPos = new RectF();
         mScrollFade = new ScrollFade();
@@ -250,7 +250,18 @@
         }
     }
 
-    private void getSections() {
+    SectionIndexer getSectionIndexer() {
+        return mSectionIndexer;
+    }
+
+    Object[] getSections() {
+        if (mListAdapter == null && mList != null) {
+            getSectionsFromIndexer();
+        }
+        return mSections;
+    }
+
+    private void getSectionsFromIndexer() {
         Adapter adapter = mList.getAdapter();
         mSectionIndexer = null;
         if (adapter instanceof HeaderViewListAdapter) {
@@ -391,8 +402,7 @@
     
     boolean onInterceptTouchEvent(MotionEvent ev) {
         if (mState > STATE_NONE && ev.getAction() == MotionEvent.ACTION_DOWN) {
-            if (ev.getX() > mList.getWidth() - mThumbW && ev.getY() >= mThumbY &&
-                    ev.getY() <= mThumbY + mThumbH) {
+            if (isPointInside(ev.getX(), ev.getY())) {
                 setState(STATE_DRAGGING);
                 return true;
             }
@@ -404,20 +414,20 @@
         if (mState == STATE_NONE) {
             return false;
         }
-        if (me.getAction() == MotionEvent.ACTION_DOWN) {
-            if (me.getX() > mList.getWidth() - mThumbW
-                    && me.getY() >= mThumbY 
-                    && me.getY() <= mThumbY + mThumbH) {
-                
+
+        final int action = me.getAction();
+
+        if (action == MotionEvent.ACTION_DOWN) {
+            if (isPointInside(me.getX(), me.getY())) {
                 setState(STATE_DRAGGING);
                 if (mListAdapter == null && mList != null) {
-                    getSections();
+                    getSectionsFromIndexer();
                 }
 
                 cancelFling();
                 return true;
             }
-        } else if (me.getAction() == MotionEvent.ACTION_UP) {
+        } else if (action == MotionEvent.ACTION_UP) {
             if (mState == STATE_DRAGGING) {
                 setState(STATE_VISIBLE);
                 final Handler handler = mHandler;
@@ -425,7 +435,7 @@
                 handler.postDelayed(mScrollFade, 1000);
                 return true;
             }
-        } else if (me.getAction() == MotionEvent.ACTION_MOVE) {
+        } else if (action == MotionEvent.ACTION_MOVE) {
             if (mState == STATE_DRAGGING) {
                 final int viewHeight = mList.getHeight();
                 // Jitter
@@ -448,7 +458,11 @@
         }
         return false;
     }
-    
+
+    boolean isPointInside(float x, float y) {
+        return x > mList.getWidth() - mThumbW && y >= mThumbY && y <= mThumbY + mThumbH;
+    }
+
     public class ScrollFade implements Runnable {
         
         long mStartTime;
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index 80fbf9e..3afd5d4 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -353,25 +353,24 @@
 
         if (mForeground != null) {
             final Drawable foreground = mForeground;
+
             if (mForegroundBoundsChanged) {
                 mForegroundBoundsChanged = false;
-                if (foreground != null) {
-                    final Rect selfBounds = mSelfBounds;
-                    final Rect overlayBounds = mOverlayBounds;
+                final Rect selfBounds = mSelfBounds;
+                final Rect overlayBounds = mOverlayBounds;
 
-                    final int w = mRight-mLeft;
-                    final int h = mBottom-mTop;
-                    
-                    if (mForegroundInPadding) {
-                        selfBounds.set(0, 0, w, h);
-                    } else {
-                        selfBounds.set(mPaddingLeft, mPaddingTop, w - mPaddingRight, h - mPaddingBottom);
-                    }
+                final int w = mRight-mLeft;
+                final int h = mBottom-mTop;
 
-                    Gravity.apply(mForegroundGravity, foreground.getIntrinsicWidth(),
-                            foreground.getIntrinsicHeight(), selfBounds, overlayBounds);
-                    foreground.setBounds(overlayBounds);
+                if (mForegroundInPadding) {
+                    selfBounds.set(0, 0, w, h);
+                } else {
+                    selfBounds.set(mPaddingLeft, mPaddingTop, w - mPaddingRight, h - mPaddingBottom);
                 }
+
+                Gravity.apply(mForegroundGravity, foreground.getIntrinsicWidth(),
+                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds);
+                foreground.setBounds(overlayBounds);
             }
             
             foreground.draw(canvas);
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 6686f75..10d8f55c 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -2852,6 +2852,9 @@
             final boolean areAllItemsSelectable = mAreAllItemsSelectable;
             final ListAdapter adapter = mAdapter;
             final boolean isOpaque = isOpaque();
+            if (isOpaque && mDividerPaint == null) {
+                mDividerPaint = new Paint();
+            }
             final Paint paint = mDividerPaint;
 
             if (!mStackFromBottom) {
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 975277b..68764a5 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -1072,6 +1072,20 @@
             mWindowManager.updateViewLayout(mPopupView, p);
         }
     }
+
+    /**
+     * <p>Updates the dimension of the popup window. Calling this function
+     * also updates the window with the current popup state as described
+     * for {@link #update()}.</p>
+     *
+     * @param width the new width
+     * @param height the new height
+     */
+    public void update(int width, int height) {
+        WindowManager.LayoutParams p = (WindowManager.LayoutParams)
+                mPopupView.getLayoutParams();
+        update(p.x, p.y, width, height, false);
+    }
     
     /**
      * <p>Updates the position and the dimension of the popup window. Width and
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 40a72a4..5c75af2c 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -127,6 +127,8 @@
  * @attr ref android.R.styleable#TextView_textColor
  * @attr ref android.R.styleable#TextView_textColorHighlight
  * @attr ref android.R.styleable#TextView_textColorHint
+ * @attr ref android.R.styleable#TextView_textAppearance
+ * @attr ref android.R.styleable#TextView_textColorLink
  * @attr ref android.R.styleable#TextView_textSize
  * @attr ref android.R.styleable#TextView_textScaleX
  * @attr ref android.R.styleable#TextView_typeface
@@ -164,13 +166,22 @@
  * @attr ref android.R.styleable#TextView_capitalize
  * @attr ref android.R.styleable#TextView_autoText
  * @attr ref android.R.styleable#TextView_editable
+ * @attr ref android.R.styleable#TextView_freezesText
+ * @attr ref android.R.styleable#TextView_ellipsize
  * @attr ref android.R.styleable#TextView_drawableTop
  * @attr ref android.R.styleable#TextView_drawableBottom
  * @attr ref android.R.styleable#TextView_drawableRight
  * @attr ref android.R.styleable#TextView_drawableLeft
+ * @attr ref android.R.styleable#TextView_drawablePadding
  * @attr ref android.R.styleable#TextView_lineSpacingExtra
  * @attr ref android.R.styleable#TextView_lineSpacingMultiplier
  * @attr ref android.R.styleable#TextView_marqueeRepeatLimit
+ * @attr ref android.R.styleable#TextView_inputType
+ * @attr ref android.R.styleable#TextView_imeOptions
+ * @attr ref android.R.styleable#TextView_privateImeOptions
+ * @attr ref android.R.styleable#TextView_imeActionLabel
+ * @attr ref android.R.styleable#TextView_imeActionId
+ * @attr ref android.R.styleable#TextView_editorExtras
  */
 @RemoteView
 public class TextView extends View implements ViewTreeObserver.OnPreDrawListener {
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index bf9bc4e..a448ac6 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -37,10 +37,8 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
-import java.util.Set;
 
 /**
  * All information we are collecting about things that can happen that impact
@@ -55,7 +53,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS' 
 
     // Current on-disk Parcel version
-    private static final int VERSION = 35;
+    private static final int VERSION = 36;
 
     private final File mFile;
     private final File mBackupFile;
@@ -105,6 +103,12 @@
     boolean mPhoneOn;
     StopwatchTimer mPhoneOnTimer;
     
+    boolean mAudioOn;
+    StopwatchTimer mAudioOnTimer;
+    
+    boolean mVideoOn;
+    StopwatchTimer mVideoOnTimer;
+    
     int mPhoneSignalStrengthBin = -1;
     final StopwatchTimer[] mPhoneSignalStrengthsTimer = 
             new StopwatchTimer[NUM_SIGNAL_STRENGTH_BINS];
@@ -142,9 +146,9 @@
      */
     int mDischargeStartLevel;
     int mDischargeCurrentLevel;
-    
+
     long mLastWriteTime = 0; // Milliseconds
-    
+
     /*
      * Holds a SamplingTimer associated with each kernel wakelock name being tracked.
      */
@@ -320,6 +324,13 @@
          */
         long mUnpluggedTime;
         
+        /**
+         * Constructs from a parcel.
+         * @param type
+         * @param unpluggables
+         * @param powerType
+         * @param in
+         */
         Timer(int type, ArrayList<Unpluggable> unpluggables, Parcel in) {
             mType = type;
             
@@ -632,7 +643,6 @@
          * was actually held for an interesting duration.
          */
         long mAcquireTime;
-        
 
         StopwatchTimer(int type, ArrayList<StopwatchTimer> timerPool,
                 ArrayList<Unpluggable> unpluggables, Parcel in) {
@@ -1071,7 +1081,51 @@
             mWifiOnUid = -1;
         }
     }
+
+    public void noteAudioOnLocked(int uid) {
+        if (!mAudioOn) {
+            mAudioOn = true;
+            mAudioOnTimer.startRunningLocked(this);
+        }
+        Uid u = mUidStats.get(uid);
+        if (u != null) {
+            u.noteAudioTurnedOnLocked();
+        }
+    }
     
+    public void noteAudioOffLocked(int uid) {
+        if (mAudioOn) {
+            mAudioOn = false;
+            mAudioOnTimer.stopRunningLocked(this);
+        }
+        Uid u = mUidStats.get(uid);
+        if (u != null) {
+            u.noteAudioTurnedOffLocked();
+        }
+    }
+
+    public void noteVideoOnLocked(int uid) {
+        if (!mVideoOn) {
+            mVideoOn = true;
+            mVideoOnTimer.startRunningLocked(this);
+        }
+        Uid u = mUidStats.get(uid);
+        if (u != null) {
+            u.noteVideoTurnedOnLocked();
+        }
+    }
+    
+    public void noteVideoOffLocked(int uid) {
+        if (mVideoOn) {
+            mVideoOn = false;
+            mVideoOnTimer.stopRunningLocked(this);
+        }
+        Uid u = mUidStats.get(uid);
+        if (u != null) {
+            u.noteVideoTurnedOffLocked();
+        }
+    }
+
     public void noteWifiRunningLocked() {
         if (!mWifiRunning) {
             mWifiRunning = true;
@@ -1151,7 +1205,7 @@
         return mScreenBrightnessTimer[brightnessBin].getTotalTimeLocked(
                 batteryRealtime, which);
     }
-    
+
     @Override public int getInputEventCount(int which) {
         return mInputEventCounter.getCountLocked(which);
     }
@@ -1159,7 +1213,7 @@
     @Override public long getPhoneOnTime(long batteryRealtime, int which) {
         return mPhoneOnTimer.getTotalTimeLocked(batteryRealtime, which);
     }
-    
+
     @Override public long getPhoneSignalStrengthTime(int strengthBin,
             long batteryRealtime, int which) {
         return mPhoneSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
@@ -1226,9 +1280,15 @@
         
         boolean mScanWifiLockOut;
         StopwatchTimer mScanWifiLockTimer;
-
+        
         boolean mWifiMulticastEnabled;
         StopwatchTimer mWifiMulticastTimer;
+        
+        boolean mAudioTurnedOn;
+        StopwatchTimer mAudioTurnedOnTimer;
+        
+        boolean mVideoTurnedOn;
+        StopwatchTimer mVideoTurnedOnTimer;
 
         Counter[] mUserActivityCounters;
         
@@ -1259,6 +1319,8 @@
             mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, null, mUnpluggables);
             mWifiMulticastTimer = new StopwatchTimer(WIFI_MULTICAST_ENABLED,
                     null, mUnpluggables);
+            mAudioTurnedOnTimer = new StopwatchTimer(AUDIO_TURNED_ON, null, mUnpluggables);
+            mVideoTurnedOnTimer = new StopwatchTimer(VIDEO_TURNED_ON, null, mUnpluggables);
         }
 
         @Override
@@ -1343,6 +1405,38 @@
         }
         
         @Override
+        public void noteVideoTurnedOnLocked() {
+            if (!mVideoTurnedOn) {
+                mVideoTurnedOn = true;
+                mVideoTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this);
+            }
+        }
+
+        @Override
+        public void noteVideoTurnedOffLocked() {
+            if (mVideoTurnedOn) {
+                mVideoTurnedOn = false;
+                mVideoTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this);
+            }
+        }
+
+        @Override
+        public void noteAudioTurnedOnLocked() {
+            if (!mAudioTurnedOn) {
+                mAudioTurnedOn = true;
+                mAudioTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this);
+            }
+        }
+
+        @Override
+        public void noteAudioTurnedOffLocked() {
+            if (mAudioTurnedOn) {
+                mAudioTurnedOn = false;
+                mAudioTurnedOnTimer.stopRunningLocked(BatteryStatsImpl.this);
+            }
+        }
+
+        @Override
         public void noteFullWifiLockReleasedLocked() {
             if (mFullWifiLockOut) {
                 mFullWifiLockOut = false;
@@ -1386,7 +1480,17 @@
         public long getWifiTurnedOnTime(long batteryRealtime, int which) {
             return mWifiTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which);
         }
-        
+
+        @Override 
+        public long getAudioTurnedOnTime(long batteryRealtime, int which) {
+            return mAudioTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which);
+        }
+
+        @Override 
+        public long getVideoTurnedOnTime(long batteryRealtime, int which) {
+            return mVideoTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which);
+        }
+
         @Override 
         public long getFullWifiLockTime(long batteryRealtime, int which) {
             return mFullWifiLockTimer.getTotalTimeLocked(batteryRealtime, which);
@@ -1437,7 +1541,7 @@
             return mCurrentTcpBytesSent + (mStartedTcpBytesSent >= 0
                     ? (NetStat.getUidTxBytes(mUid) - mStartedTcpBytesSent) : 0);
         }
-        
+
         void writeToParcelLocked(Parcel out, long batteryRealtime) {
             out.writeInt(mWakelockStats.size());
             for (Map.Entry<String, Uid.Wakelock> wakelockEntry : mWakelockStats.entrySet()) {
@@ -1475,6 +1579,8 @@
             out.writeLong(mTcpBytesSentAtLastUnplug);
             mWifiTurnedOnTimer.writeToParcel(out, batteryRealtime);
             mFullWifiLockTimer.writeToParcel(out, batteryRealtime);
+            mAudioTurnedOnTimer.writeToParcel(out, batteryRealtime);
+            mVideoTurnedOnTimer.writeToParcel(out, batteryRealtime);
             mScanWifiLockTimer.writeToParcel(out, batteryRealtime);
             mWifiMulticastTimer.writeToParcel(out, batteryRealtime);
             if (mUserActivityCounters == null) {
@@ -1534,6 +1640,10 @@
             mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON, null, mUnpluggables, in);
             mFullWifiLockOut = false;
             mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK, null, mUnpluggables, in);
+            mAudioTurnedOn = false;
+            mAudioTurnedOnTimer = new StopwatchTimer(AUDIO_TURNED_ON, null, mUnpluggables, in);
+            mVideoTurnedOn = false;
+            mVideoTurnedOnTimer = new StopwatchTimer(VIDEO_TURNED_ON, null, mUnpluggables, in);
             mScanWifiLockOut = false;
             mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, null, mUnpluggables, in);
             mWifiMulticastEnabled = false;
@@ -2327,7 +2437,7 @@
             StopwatchTimer t = getSensorTimerLocked(Sensor.GPS, false);
             if (t != null) {
                 t.stopRunningLocked(BatteryStatsImpl.this);
-            }  
+            }
         }
 
         public BatteryStatsImpl getBatteryStats() {
@@ -2764,6 +2874,10 @@
             u.mWifiTurnedOnTimer.readSummaryFromParcelLocked(in);
             u.mFullWifiLockOut = false;
             u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
+            u.mAudioTurnedOn = false;
+            u.mAudioTurnedOnTimer.readSummaryFromParcelLocked(in);
+            u.mVideoTurnedOn = false;
+            u.mVideoTurnedOnTimer.readSummaryFromParcelLocked(in);
             u.mScanWifiLockOut = false;
             u.mScanWifiLockTimer.readSummaryFromParcelLocked(in);
             u.mWifiMulticastEnabled = false;
@@ -3063,6 +3177,7 @@
         for (int ikw = 0; ikw < NKW; ikw++) {
             if (in.readInt() != 0) {
                 String wakelockName = in.readString();
+                in.readInt(); // Extra 0/1 written by Timer.writeTimerToParcel
                 SamplingTimer kwlt = new SamplingTimer(mUnpluggables, mOnBattery, in);
                 mKernelWakelockStats.put(wakelockName, kwlt);
             }
diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java
new file mode 100644
index 0000000..f08dddd
--- /dev/null
+++ b/core/java/com/android/internal/os/PowerProfile.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+
+import android.content.Context;
+import android.content.res.XmlResourceParser;
+
+import com.android.internal.util.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.HashMap;
+
+/**
+ * Reports power consumption values for various device activities. Reads values from an XML file.
+ * Customize the XML file for different devices.
+ * [hidden]
+ */
+public class PowerProfile {
+
+    /**
+     * No power consumption, or accounted for elsewhere.
+     */
+    public static final String POWER_NONE = "none";
+
+    /**
+     * Power consumption when CPU is in power collapse mode.
+     */
+    public static final String POWER_CPU_IDLE = "cpu.idle";
+
+    /**
+     * Power consumption when CPU is running at normal speed.
+     */
+    public static final String POWER_CPU_NORMAL = "cpu.normal";
+
+    /**
+     * Power consumption when CPU is running at full speed.
+     */
+    public static final String POWER_CPU_FULL = "cpu.full";
+
+    /**
+     * Power consumption when WiFi driver is scanning for networks.
+     */
+    public static final String POWER_WIFI_SCAN = "wifi.scan";
+
+    /**
+     * Power consumption when WiFi driver is on.
+     */
+    public static final String POWER_WIFI_ON = "wifi.on";
+
+    /**
+     * Power consumption when WiFi driver is transmitting/receiving.
+     */
+    public static final String POWER_WIFI_ACTIVE = "wifi.active";
+
+    /**
+     * Power consumption when GPS is on.
+     */
+    public static final String POWER_GPS_ON = "gps.on";
+
+    /**
+     * Power consumption when Bluetooth driver is on.
+     */
+    public static final String POWER_BLUETOOTH_ON = "bluetooth.on";
+
+    /**
+     * Power consumption when Bluetooth driver is transmitting/receiving.
+     */
+    public static final String POWER_BLUETOOTH_ACTIVE = "bluetooth.active";
+
+    /**
+     * Power consumption when screen is on, not including the backlight power.
+     */
+    public static final String POWER_SCREEN_ON = "screen.on";
+
+    /**
+     * Power consumption when cell radio is on but not on a call.
+     */
+    public static final String POWER_RADIO_ON = "radio.on";
+
+    /**
+     * Power consumption when talking on the phone.
+     */
+    public static final String POWER_RADIO_ACTIVE = "radio.active";
+
+    /**
+     * Power consumption at full backlight brightness. If the backlight is at
+     * 50% brightness, then this should be multiplied by 0.5
+     */
+    public static final String POWER_SCREEN_FULL = "screen.full";
+
+    /**
+     * Power consumed by the audio hardware when playing back audio content. This is in addition
+     * to the CPU power, probably due to a DSP and / or amplifier.
+     */
+    public static final String POWER_AUDIO = "dsp.audio";
+
+    /**
+     * Power consumed by any media hardware when playing back video content. This is in addition
+     * to the CPU power, probably due to a DSP.
+     */
+    public static final String POWER_VIDEO = "dsp.video";
+
+    static final HashMap<String, Double> sPowerMap = new HashMap<String, Double>();
+
+    private static final String TAG_DEVICE = "device";
+    private static final String TAG_ITEM = "item";
+    private static final String ATTR_NAME = "name";
+
+    public PowerProfile(Context context, CharSequence profile) {
+        // Read the XML file for the given profile (normally only one per
+        // device)
+        if (sPowerMap.size() == 0) {
+            readPowerValuesFromXml(context, profile);
+        }
+    }
+
+    private void readPowerValuesFromXml(Context context, CharSequence profile) {
+        // FIXME
+        //int id = context.getResources().getIdentifier(profile.toString(), "xml", 
+        //        "com.android.internal");
+        int id = com.android.internal.R.xml.power_profile_default;
+        XmlResourceParser parser = context.getResources().getXml(id);
+
+        try {
+            XmlUtils.beginDocument(parser, TAG_DEVICE);
+
+            while (true) {
+                XmlUtils.nextElement(parser);
+
+                String element = parser.getName(); 
+                if (element == null || !(element.equals(TAG_ITEM))) {
+                    break;
+                }
+
+                String name = parser.getAttributeValue(null, ATTR_NAME);
+                if (parser.next() == XmlPullParser.TEXT) {
+                    String power = parser.getText();
+                    double value = 0;
+                    try {
+                        value = Double.valueOf(power);
+                    } catch (NumberFormatException nfe) {
+                    }
+                    sPowerMap.put(name, value);
+                }
+            }
+        } catch (XmlPullParserException e) {
+            throw new RuntimeException(e);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        } finally {
+            parser.close();
+        }
+    }
+
+    /**
+     * Returns the average current in mA consumed by the subsystem 
+     * @param type the subsystem type
+     * @return the average current in milliAmps.
+     */
+    public double getAveragePower(String type) {
+        if (sPowerMap.containsKey(type)) {
+            return sPowerMap.get(type);
+        } else {
+            return 0;
+        }
+    }
+}
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index 75aa458..3e27978 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -14,9 +14,13 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "Sensors"
+#define LOG_TAG "SensorManager"
+
+#define LOG_NDEBUG 0
+#include "utils/Log.h"
 
 #include <hardware/sensors.h>
+#include <cutils/native_handle.h>
 
 #include "jni.h"
 #include "JNIHelp.h"
@@ -106,12 +110,33 @@
 }
 
 static jint
-sensors_data_open(JNIEnv *env, jclass clazz, jobject fdo)
+sensors_data_open(JNIEnv *env, jclass clazz, jobjectArray fdArray, jintArray intArray)
 {
     jclass FileDescriptor = env->FindClass("java/io/FileDescriptor");
-    jfieldID offset = env->GetFieldID(FileDescriptor, "descriptor", "I");
-    int fd = env->GetIntField(fdo, offset);
-    return sSensorDevice->data_open(sSensorDevice, fd); // doesn't take ownership of fd
+    jfieldID fieldOffset = env->GetFieldID(FileDescriptor, "descriptor", "I");
+    int numFds = (fdArray ? env->GetArrayLength(fdArray) : 0);
+    int numInts = (intArray ? env->GetArrayLength(intArray) : 0);
+    native_handle_t* handle = native_handle_create(numFds, numInts);
+    int offset = 0;
+
+    for (int i = 0; i < numFds; i++) {
+        jobject fdo = env->GetObjectArrayElement(fdArray, i);
+        if (fdo) {
+            handle->data[offset++] = env->GetIntField(fdo, fieldOffset);
+        } else {
+            handle->data[offset++] = -1;
+        }
+    }
+    if (numInts > 0) {
+        jint* ints = env->GetIntArrayElements(intArray, 0);
+        for (int i = 0; i < numInts; i++) {
+            handle->data[offset++] = ints[i];
+        }
+        env->ReleaseIntArrayElements(intArray, ints, 0);
+    }
+
+    // doesn't take ownership of the native handle
+    return sSensorDevice->data_open(sSensorDevice, handle);
 }
 
 static jint
@@ -157,7 +182,7 @@
                                             (void*)sensors_module_get_next_sensor },
     {"sensors_data_init", "()I",            (void*)sensors_data_init },
     {"sensors_data_uninit", "()I",          (void*)sensors_data_uninit },
-    {"sensors_data_open",  "(Ljava/io/FileDescriptor;)I",  (void*)sensors_data_open },
+    {"sensors_data_open",  "([Ljava/io/FileDescriptor;[I)I",  (void*)sensors_data_open },
     {"sensors_data_close", "()I",           (void*)sensors_data_close },
     {"sensors_data_poll",  "([F[I[J)I",     (void*)sensors_data_poll },
 };
diff --git a/core/jni/android_media_AudioRecord.cpp b/core/jni/android_media_AudioRecord.cpp
index 288433a..e71e348 100644
--- a/core/jni/android_media_AudioRecord.cpp
+++ b/core/jni/android_media_AudioRecord.cpp
@@ -45,8 +45,6 @@
     jmethodID postNativeEventInJava; //... event post callback method
     int       PCM16;                 //...  format constants
     int       PCM8;                  //...  format constants
-    int       SOURCE_DEFAULT;        //...  record source constants
-    int       SOURCE_MIC;            //...  record source constants
     jfieldID  nativeRecorderInJavaObj; // provides access to the C++ AudioRecord object
     jfieldID  nativeCallbackCookie;    // provides access to the AudioRecord callback data
 };
@@ -66,7 +64,7 @@
 #define AUDIORECORD_ERROR_SETUP_ZEROFRAMECOUNT      -16
 #define AUDIORECORD_ERROR_SETUP_INVALIDCHANNELCOUNT -17
 #define AUDIORECORD_ERROR_SETUP_INVALIDFORMAT       -18
-#define AUDIORECORD_ERROR_SETUP_INVALIDSTREAMTYPE   -19
+#define AUDIORECORD_ERROR_SETUP_INVALIDSOURCE       -19
 #define AUDIORECORD_ERROR_SETUP_NATIVEINITFAILED    -20
 
 jint android_media_translateRecorderErrorCode(int code) {
@@ -154,17 +152,16 @@
     int frameSize = nbChannels * bytesPerSample;
     size_t frameCount = buffSizeInBytes / frameSize;
     
-    // compare the source against the Java constants
-    AudioRecord::stream_type arSource;
-    if (source == javaAudioRecordFields.SOURCE_DEFAULT) {
-        arSource = AudioRecord::DEFAULT_INPUT;
-    } else if (source == javaAudioRecordFields.SOURCE_MIC) {
-        arSource = AudioRecord::MIC_INPUT;
-    } else {
+    // convert and check input source value
+    // input_source values defined in AudioRecord.h are equal to
+    // JAVA MediaRecord.AudioSource values minus 1.
+    AudioRecord::input_source arSource = (AudioRecord::input_source)(source - 1);
+    if (arSource < AudioRecord::DEFAULT_INPUT ||
+        arSource >= AudioRecord::NUM_INPUT_SOURCES) {
         LOGE("Error creating AudioRecord: unknown source.");
-        return AUDIORECORD_ERROR_SETUP_INVALIDSTREAMTYPE;
+        return AUDIORECORD_ERROR_SETUP_INVALIDSOURCE;
     }
-     
+
     audiorecord_callback_cookie *lpCallbackData = NULL;
     AudioRecord* lpRecorder = NULL;
 
@@ -511,8 +508,6 @@
 #define JAVA_POSTEVENT_CALLBACK_NAME  "postEventFromNative"
 #define JAVA_CONST_PCM16_NAME         "ENCODING_PCM_16BIT"
 #define JAVA_CONST_PCM8_NAME          "ENCODING_PCM_8BIT"
-#define JAVA_CONST_SOURCEDEFAULT_NAME "SOURCE_DEFAULT"
-#define JAVA_CONST_SOURCEMIC_NAME     "SOURCE_MIC"
 #define JAVA_NATIVERECORDERINJAVAOBJ_FIELD_NAME  "mNativeRecorderInJavaObj"
 #define JAVA_NATIVECALLBACKINFO_FIELD_NAME       "mNativeCallbackCookie"
 
@@ -583,17 +578,6 @@
         return -1;
     }
 
-    // Get the recording source constants from the AudioRecord class
-    if ( !android_media_getIntConstantFromClass(env, javaAudioRecordFields.audioRecordClass, 
-                kClassPathName,
-                JAVA_CONST_SOURCEDEFAULT_NAME, &(javaAudioRecordFields.SOURCE_DEFAULT))
-        || !android_media_getIntConstantFromClass(env, javaAudioRecordFields.audioRecordClass, 
-                kClassPathName,
-                JAVA_CONST_SOURCEMIC_NAME, &(javaAudioRecordFields.SOURCE_MIC)) ) {
-        // error log performed in getIntConstantFromClass() 
-        return -1;
-    }
-
     return AndroidRuntime::registerNativeMethods(env,
             kClassPathName, gMethods, NELEM(gMethods));
 }
diff --git a/core/jni/android_net_wifi_Wifi.cpp b/core/jni/android_net_wifi_Wifi.cpp
index 25670df..9f93e2f 100644
--- a/core/jni/android_net_wifi_Wifi.cpp
+++ b/core/jni/android_net_wifi_Wifi.cpp
@@ -317,8 +317,13 @@
     }
     // reply comes back in the form "<SSID> rssi XX" where XX is the
     // number we're interested in.  if we're associating, it returns "OK".
+    // beware - <SSID> can contain spaces.
     if (strcmp(reply, "OK") != 0) {
-    	sscanf(reply, "%*s %*s %d", &rssi);
+        char* lastSpace = strrchr(reply, ' ');
+        // lastSpace should be preceded by "rssi" and followed by the value
+        if (lastSpace && !strncmp(lastSpace - 4, "rssi", 4)) {
+            sscanf(lastSpace + 1, "%d", &rssi);
+        }
     }
     return (jint)rssi;
 }
diff --git a/core/res/res/layout/list_gestures_overlay.xml b/core/res/res/layout/list_gestures_overlay.xml
new file mode 100644
index 0000000..54d72c8
--- /dev/null
+++ b/core/res/res/layout/list_gestures_overlay.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<android.gesture.GestureOverlayView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent" />
diff --git a/core/res/res/layout/search_dropdown_item_icons_2line.xml b/core/res/res/layout/search_dropdown_item_icons_2line.xml
index 0d07490..2710b3b 100644
--- a/core/res/res/layout/search_dropdown_item_icons_2line.xml
+++ b/core/res/res/layout/search_dropdown_item_icons_2line.xml
@@ -67,13 +67,10 @@
         android:textAppearance="?android:attr/textAppearanceSearchResultTitle"
         android:singleLine="true"
         android:layout_width="fill_parent"
-        android:layout_height="29dip"
-        android:paddingTop="4dip"
-        android:gravity="center_vertical"
-        android:layout_alignParentTop="true"
+        android:layout_height="wrap_content"
+        android:layout_centerVertical="true"
         android:layout_toRightOf="@android:id/icon1"
         android:layout_toLeftOf="@android:id/icon2"
-        android:layout_above="@android:id/text2"
-        android:layout_alignWithParentIfMissing="true" />
+        android:layout_above="@android:id/text2" />
     
 </RelativeLayout>
diff --git a/core/res/res/raw/latin_lowercase b/core/res/res/raw/latin_lowercase
index 9c747d6..17cfaf0 100644
--- a/core/res/res/raw/latin_lowercase
+++ b/core/res/res/raw/latin_lowercase
Binary files differ
diff --git a/core/res/res/values-ja/donottranslate.xml b/core/res/res/values-ja/donottranslate.xml
new file mode 100644
index 0000000..f7c3566
--- /dev/null
+++ b/core/res/res/values-ja/donottranslate.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Default text encoding for WebSettings. -->
+    <string name="default_text_encoding">Shift_JIS</string>
+</resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 60c70cf..8c4b714 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -324,6 +324,8 @@
         <attr name="expandableListViewStyle" format="reference" />
         <!-- Default Gallery style. -->
         <attr name="galleryStyle" format="reference" />
+        <!-- Default GestureOverlayView style. -->
+        <attr name="gestureOverlayViewStyle" format="reference" />
         <!-- Default GridView style. -->
         <attr name="gridViewStyle" format="reference" />
         <!-- The style resource to use for an ImageButton -->
@@ -1379,6 +1381,19 @@
              will use only the number of items in the adapter and the number of items visible
              on screen to determine the scrollbar's properties. -->
         <attr name="smoothScrollbar" format="boolean" />
+        <!-- Defines the type of gesture to enable for the widget. -->
+        <attr name="gestures">
+            <!-- No gesture -->
+            <enum name="none" value="0" />
+            <!-- Gestures jump to a specific position in the content. This requires
+                  fast scroll to be enabled. If fast scroll is enabled from XML,
+                  jump gestures will be enabled automatically. -->
+            <enum name="jump" value="1" />
+            <!-- Gestures filter the content. This requires text filtering to be enabled.
+                 If text filtering is enabled from XML, filter gestures will be enabled
+                 automatically. -->
+            <enum name="filter" value="2" />
+        </attr>
     </declare-styleable>
     <declare-styleable name="AbsSpinner">
         <!-- Reference to an array resource that will populate the Spinner.  For static content,
@@ -1581,7 +1596,7 @@
         <!-- Height of the divider. Will use the intrinsic height of the divider if this
              is not specified. -->
         <attr name="dividerHeight" format="dimension" />
-        <!-- Defines the choice behavior for the List. By default, Lists do not have
+        <!-- Defines the choice behavior for the ListView. By default, lists do not have
              any choice behavior. By setting the choiceMode to singleChoice, the List
              allows up to one item to be in a chosen state. By setting the choiceMode to
              multipleChoice, the list allows any number of items to be chosen. -->
@@ -2061,6 +2076,44 @@
         <attr name="animateOnClick" format="boolean" />
     </declare-styleable>
 
+    <!-- GestureOverlayView specific attributes. These attributes are used to configure
+         a GestureOverlayView from XML. -->
+    <declare-styleable name="GestureOverlayView">
+        <!-- Width of the stroke used to draw the gesture. -->
+        <attr name="gestureStrokeWidth" format="float" />
+        <!-- Color used to draw a gesture. -->
+        <attr name="gestureColor" format="color" />
+        <!-- Color used to draw the user's strokes until we are sure it's a gesture. -->
+        <attr name="uncertainGestureColor" format="color" />
+        <!-- Time, in milliseconds, to wait before the gesture fades out after the user
+             is done drawing it. -->
+        <attr name="fadeOffset" format="integer" />
+        <!-- Duration, in milliseconds, of the fade out effect after the user is done
+             drawing a gesture. -->
+        <attr name="fadeDuration" format="integer" />
+        <!-- Defines the type of strokes that define a gesture. -->
+        <attr name="gestureStrokeType">
+            <!-- A gesture is made of only one stroke. -->
+            <enum name="single" value="0" />
+            <!-- A gesture is made of multiple strokes. -->
+            <enum name="multiple" value="1" />
+        </attr>
+        <!-- Minimum length of a stroke before it is recognized as a gesture. -->
+        <attr name="gestureStrokeLengthThreshold" format="float" />
+        <!-- Squareness threshold of a stroke before it is recognized as a gesture. -->
+        <attr name="gestureStrokeSquarenessThreshold" format="float" />
+        <!-- Minimum curve angle a stroke must contain before it is recognized as a gesture. -->
+        <attr name="gestureStrokeAngleThreshold" format="float" />
+        <!-- Defines whether the overlay should intercept the motion events when a gesture
+             is recognized. -->
+        <attr name="eventsInterceptionEnabled" format="boolean" />
+        <!-- Defines whether the gesture will automatically fade out after being recognized. -->
+        <attr name="fadeEnabled" format="boolean" />
+        <!-- Indicates whether horizontal (when the orientation is vertical) or vertical
+             (when orientation is horizontal) strokes automatically define a gesture. -->
+        <attr name="orientation" />
+    </declare-styleable>
+
     <!-- ======================================= -->
     <!-- Widget package parent layout attributes -->
     <!-- ======================================= -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 83ac8e2..f655b27 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -34,4 +34,8 @@
     
     <!-- The duration (in milliseconds) of a long animation. -->
     <integer name="config_longAnimTime">300</integer>
+
+    <!-- Flag indicating whether Last Name comes before First Name.
+        This becomes true in Japan, for example.-->
+    <bool name="config_lastname_comes_before_firstname">false</bool>
 </resources>
diff --git a/core/res/res/values/donottranslate.xml b/core/res/res/values/donottranslate.xml
new file mode 100644
index 0000000..6def3bf
--- /dev/null
+++ b/core/res/res/values/donottranslate.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- Default text encoding for WebSettings. -->
+    <string name="default_text_encoding">Latin-1</string>
+</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 5eec448..3c3b2d9 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1101,7 +1101,19 @@
   <public type="attr" name="maxSdkVersion" />
   <public type="attr" name="testOnly" />
   <public type="attr" name="contentDescription" />
-  
+  <public type="attr" name="gestureStrokeWidth" />
+  <public type="attr" name="gestureColor" />
+  <public type="attr" name="uncertainGestureColor" />
+  <public type="attr" name="fadeOffset" />
+  <public type="attr" name="fadeDuration" />
+  <public type="attr" name="gestures" />
+  <public type="attr" name="gestureStrokeType" />
+  <public type="attr" name="gestureStrokeLengthThreshold" />
+  <public type="attr" name="gestureStrokeSquarenessThreshold" />
+  <public type="attr" name="gestureStrokeAngleThreshold" />
+  <public type="attr" name="eventsInterceptionEnabled" />
+  <public type="attr" name="fadeEnabled" />
+
   <public-padding type="attr" name="donut_resource_pad" end="0x0101029f" />
 
   <public-padding type="id" name="donut_resource_pad" end="0x01020040" />
@@ -1132,12 +1144,13 @@
   
   
 <!-- ===============================================================
-     Resources added in version 5 of the platform.
+     Resources added in Eclair.
      =============================================================== -->
   <eat-comment />
 
-  <public type="attr" name="accountType" id="0x010102A9" />
-  <public type="attr" name="contentAuthority" id="0x010102AA" />
+  <public type="attr" name="accountType" />
+  <public type="attr" name="contentAuthority" />
+
   <public type="drawable" name="stat_sys_vp_phone_call" />
   <public type="drawable" name="stat_sys_vp_phone_call_on_hold" />
   
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 5bd8308..6512006 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1968,8 +1968,11 @@
     <!-- This string appears (on two lines) when you type a number into contacts search, to let you create a contact whose phone number is the number you typed.  The first line will be in bigger type than the second. -->
     <string name="create_contact_using">Create contact\nusing <xliff:g id="number" example="555">%s</xliff:g></string>
 
-    <!-- This string array should be overridden by the manufacture to present a list of carrier-id,locale pairs.  This is used at startup to set a default locale by checking the system property ro.carrier for the carrier-id and searching through this array -->
-    <string-array translatable="false" name="carrier_locales">
+    <!-- This string array should be overridden by the manufacture to present a list of carrier-id,locale,wifi-channel sets.  This is used at startup to set system defaults by checking the system property ro.carrier for the carrier-id and searching through this array -->
+    <!-- An Array of [[Carrier-ID]                     -->
+    <!--              [default-locale]                 -->
+    <!--              [default-wifi-allowed-channels]] -->
+    <string-array translatable="false" name="carrier_properties">
     </string-array>
 
      <!-- Title for the selected state of a CompoundButton. -->
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 8160c9c..490abde 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -171,6 +171,23 @@
         <item name="android:fadingEdge">vertical</item>
     </style>
 
+    <style name="Widget.GestureOverlayView">
+        <item name="android:gestureStrokeWidth">12.0</item>
+        <item name="android:gestureColor">#ffffff00</item>
+        <item name="android:uncertainGestureColor">#48ffff00</item>
+        <item name="android:fadeOffset">420</item>
+        <item name="android:fadeDuration">150</item>
+        <item name="android:gestureStrokeLengthThreshold">30.0</item>
+        <item name="android:gestureStrokeSquarenessThreshold">0.275</item>
+        <item name="android:gestureStrokeAngleThreshold">40.0</item>
+        <item name="android:eventsInterceptionEnabled">true</item>
+    </style>
+
+    <style name="Widget.GestureOverlayView.White">
+        <item name="android:gestureColor">#ff00ff00</item>
+        <item name="android:uncertainGestureColor">#4800ff00</item>
+    </style>
+
     <style name="Widget.Button">
         <item name="android:background">@android:drawable/btn_default</item>
         <item name="android:focusable">true</item>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index b168fb8..1c87220 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -142,7 +142,8 @@
         <item name="editTextStyle">@android:style/Widget.EditText</item>
         <item name="expandableListViewStyle">@android:style/Widget.ExpandableListView</item>
         <item name="galleryStyle">@android:style/Widget.Gallery</item>
-        <item name="gridViewStyle">@android:style/Widget.GridView</item>        
+        <item name="gestureOverlayViewStyle">@android:style/Widget.GestureOverlayView</item>
+        <item name="gridViewStyle">@android:style/Widget.GridView</item>
         <item name="imageButtonStyle">@android:style/Widget.ImageButton</item>
         <item name="imageWellStyle">@android:style/Widget.ImageWell</item>
         <item name="listViewStyle">@android:style/Widget.ListView</item>
@@ -225,6 +226,7 @@
         <item name="textCheckMark">@android:drawable/indicator_check_mark_light</item>
         <item name="textCheckMarkInverse">@android:drawable/indicator_check_mark_dark</item>
 
+        <item name="gestureOverlayViewStyle">@android:style/Widget.GestureOverlayView.White</item>
         <item name="listViewStyle">@android:style/Widget.ListView.White</item>
         <item name="listDivider">@drawable/divider_horizontal_bright</item>
         <item name="listSeparatorTextViewStyle">@android:style/Widget.TextView.ListSeparator.White</item>
@@ -366,6 +368,12 @@
         <item name="android:backgroundDimEnabled">true</item>
         <item name="windowContentOverlay">@null</item>        
     </style>
+    
+    <!-- Theme for the search input bar when doing global search. The only
+         difference from non-global search is that we do not dim the background. -->
+    <style name="Theme.GlobalSearchBar" parent="Theme.Panel">
+        <item name="windowContentOverlay">@null</item>
+    </style>
 
     <!-- Menu Themes -->
     <eat-comment />
diff --git a/core/res/res/xml/power_profile_default.xml b/core/res/res/xml/power_profile_default.xml
new file mode 100644
index 0000000..d265b46
--- /dev/null
+++ b/core/res/res/xml/power_profile_default.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+**
+** Copyright 2009, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License")
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<device name="Android">
+  <item name="none">0</item>
+  <item name="screen.on">30</item>
+  <item name="bluetooth.active">103</item>
+  <item name="bluetooth.on">5</item>
+  <item name="screen.full">144</item>
+  <item name="wifi.on">23</item>
+  <item name="wifi.active">200</item>
+  <item name="wifi.scan">200</item>
+  <item name="cpu.idle">1.6</item>
+  <item name="cpu.normal">100</item>
+  <item name="cpu.full">140</item>
+  <item name="dsp.audio">70</item>
+  <item name="dsp.video">100</item>
+  <item name="radio.on">3</item>
+  <item name="radio.active">175</item>
+</device>
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 6d750b3..33d6b3b 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -138,6 +138,8 @@
     <assign-permission name="android.permission.ACCESS_DRM" uid="media" />
     <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="media" />
 
+    <assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="graphics" />
+
     <!-- This is a list of all the libraries available for application
          code to link against. -->
 
diff --git a/data/fonts/DroidSansJapanese.ttf b/data/fonts/DroidSansJapanese.ttf
index ca79221..412fa3d 100755
--- a/data/fonts/DroidSansJapanese.ttf
+++ b/data/fonts/DroidSansJapanese.ttf
Binary files differ
diff --git a/docs/html/guide/appendix/media-formats.jd b/docs/html/guide/appendix/media-formats.jd
index a3cc0ff..db5a15e 100644
--- a/docs/html/guide/appendix/media-formats.jd
+++ b/docs/html/guide/appendix/media-formats.jd
@@ -2,8 +2,9 @@
 @jd:body
 
 <p>The <a href="#core">Core Media Formats</a> table below describes the media format support built into the Android platform. Note that any given mobile device may provide support for additional formats or file types not listed in the table. </p>
-<p>For your convenience, the table <a href="#g1">T-Mobile G1 Media Formats</a> describes additional media format details for the T-Mobile G1 device. </p>
+<p>For your convenience, the table <a href="#g1">T-Mobile G1 Media Formats</a> describes additional media formats and characteristics provided by the T-Mobile G1 device. Other devices may support additional formats not listed on this page. </p>
 
+<p>As an application developer, you are free to make use of any media codec that is available on any Android-powered device, including those provided by the Android platform and those that are device-specific.</p>
 
 <h2 id="core">Core Media Formats</h2>
 
@@ -130,7 +131,7 @@
 <td style="text-align: center;">X</td>
 <td style="text-align: center;">X</td>
 <td>&nbsp;</td>
-<td>3GPP (.3gp)</td>
+<td>3GPP (.3gp) and MPEG-4 (.mp4)</td>
 </tr>
 
 <tr>
@@ -151,9 +152,9 @@
 
 </tbody></table>
 
-<h2 id="g1">T-Mobile G1 Media Formats</h2>
+<h2 id="g1">T-Mobile G1 Media Formats and Characteristics</h2>
 
-<p>In addition to the core media formats supported in the Android platform, the T-Mobile G1 also supports the formats listed below.</p>
+<p>The table below lists media formats supported by the T-Mobile G1 in addition to those provided as part of the Android platform. This table also details G1-specific performance characteristics of some Android core media formats.</p>
 
 <table>
 <tbody>
@@ -163,7 +164,7 @@
 <th>Format</th>
 <th>Encoder</th>
 <th>Decoder</th>
-<th>Details</th>
+<th>Comment</th>
 <th>File Type(s) Supported</th>
 </tr>
 
@@ -178,13 +179,13 @@
 <li>L2: &lt;=161 kbps &lt;=48 kHz</li>
 <li>L3: &lt;385 kbps &lt;=48 kHz</li>
 </ul>
-Mono and stereo profiles with 16-bits per sample. Decoder does not support WMA Pro, Lossless, or Speech codecs.
+Mono and stereo profiles with 16-bits per sample. Decoder does not support WMA Pro, Lossless, or Speech codecs. 
 </td>
 <td>Windows Media Audio (.wma)</td>
 </tr>
 
 <tr>
-<td rowspan="3">Video</td>
+<td rowspan="2">Video</td>
 <td>WMV</td>
 <td>&nbsp;</td>
 <td style="text-align: center;">X</td>
@@ -193,22 +194,16 @@
 </tr>
 
 <tr>
-<td>H.263</td>
-<td style="text-align: center;">X</td>
-<td style="text-align: center;">X</td>
-<td>&nbsp;</td>
-<td>3GPP (.3gp) and MPEG-4 (.mp4)</td>
-</tr>
-
-<tr>
 <td>H.264&nbsp;AVC</td>
 <td>&nbsp;</td>
 <td style="text-align: center;">X</td>
-<td>Limited to baseline profile up to 480x320, and 600 kbps average bitrate for the video stream.</td>
+<td>On the G1, this decoder is limited to baseline profile up to 480x320, and 600 kbps average bitrate for the video stream.</td>
 <td>3GPP (.3gp) and MPEG-4 (.mp4)</td>
 </tr>
 
 </tbody></table>
 
 
-<p>Note that Windows Media codecs are not part of the Android platform and require special licensing from Microsoft or an authorized developer such as Packet Video.</p>
+
+
+
diff --git a/docs/html/guide/developing/eclipse-adt.jd b/docs/html/guide/developing/eclipse-adt.jd
index 75f3d78..3b3bb38 100644
--- a/docs/html/guide/developing/eclipse-adt.jd
+++ b/docs/html/guide/developing/eclipse-adt.jd
@@ -38,15 +38,15 @@
 
 <p>To begin developing Android applications in the Eclipse IDE with ADT, you first need to 
 download the Eclipse IDE and then download and install the ADT plugin. To do so, follow the 
-steps given in <a href="{@docRoot}sdk/1.5_r1/installing.html#installingplugin">Installing 
+steps given in <a href="{@docRoot}sdk/{@sdkCurrent}/installing.html#installingplugin">Installing 
 the ADT Plugin</a>.</p>
 
 <p>If you are already developing applications using a version of ADT earlier than 0.9, make
 sure to upgrade to the latest version before continuing. See the guide to
-<a href="{@docRoot}sdk/1.5_r1/upgrading.html#UpdateAdt">Update Your Eclipse ADT Plugin</a>.</p>
+<a href="{@docRoot}sdk/{@sdkCurrent}/upgrading.html#UpdateAdt">Updating Your Eclipse ADT Plugin</a>.</p>
 
 <p class="note"><strong>Note:</strong> This guide assumes you are using the latest version of
-the ADT plugin (0.9). While most of the information covered also applies to previous 
+the ADT plugin. While most of the information covered also applies to previous 
 versions, if you are using an older version, you may want to consult this document from
 the set of documentation included in your SDK package (instead of the online version).</p>
 
@@ -138,9 +138,9 @@
 <p><em>Wait!</em> Before you can run your application on the Android Emulator, 
 you <strong>must</strong> create an Android Virtual Device (AVD). 
 An AVD is a configuration that specifies the Android platform to be used on the emulator.
-You can read more about AVDs in the <a href="{@docRoot}guide/developing/index.html#avd">Developing
-Overview</a>, but if you just want to get started, follow the simple guide below to create
-an AVD.</p>
+You can read more in the <a href="{@docRoot}guide/developing/tools/avd.html">Android Virtual
+Devices</a> document, but if you just want to get started, follow the simple guide below to
+create an AVD.</p>
 
 <p>If you will be running your applications only on actual device hardware, you do not 
 need an AVD &mdash; see 
diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs
index a044cea..da5192a 100644
--- a/docs/html/guide/guide_toc.cs
+++ b/docs/html/guide/guide_toc.cs
@@ -146,6 +146,7 @@
       <li class="toggle-list">
         <div><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/index.html">UI Guidelines</a></div>
           <ul>
+            <li><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/icon_design.html">Icon Design</a></li>
             <li><a href="<?cs var:toroot ?>guide/practices/ui_guidelines/widget_design.html">App Widget Design</a></li>
           </ul>
       </li>
diff --git a/docs/html/guide/practices/ui_guidelines/icon_design.jd b/docs/html/guide/practices/ui_guidelines/icon_design.jd
new file mode 100644
index 0000000..155684a
--- /dev/null
+++ b/docs/html/guide/practices/ui_guidelines/icon_design.jd
@@ -0,0 +1,1406 @@
+page.title=Icon Design Guidelines
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>Icon design quickview</h2>
+
+<ul>
+<li>You can use several types of icons in an Android application.</li>
+<li>Your icons should follow the specification in this document.</li>
+<li>A set of standard icons is provided by the Android platform. Your
+application can use the standard icons by referencing them as resources.</li>
+</ul>
+
+<h2>In this document</h2>
+
+<ol>
+<li><a href="#launcherstructure">Launcher icon</a></li>
+<li><a href="#menustructure">Menu icon</a></li>
+<li><a href="#statusbarstructure">Status bar icon</a></li>
+<li><a href="#tabstructure">Tab icon</a></li>
+<li><a href="#dialogstructure">Dialog icon</a></li>
+<li><a href="#listviewstructure">List view icon</a></li>
+
+<li style="margin-top:4px;"><a href="#dodonts">General guidelines</a></li>
+<li><a href="#templatespack">Using the Icon Templates Pack</a></li>
+<li><a href="#file">Icon appendix</a>
+	<ol>
+	<li><a href="#launcherapx">Launcher icons</a></li>
+	<li><a href="#menuapx">Menu icons</a></li>
+	<li><a href="#statusbarapx">Status bar icons</a></li>
+	</ol>
+</li>
+
+</ol>
+
+<h2>See also</h2>
+
+<ol>
+<li><a href="{@docRoot}shareables/icon_templates-v1.0.zip">Android Icon
+Templates Pack &raquo;</a></li>
+</ol>
+
+</div>
+</div>
+
+<p>Creating a unified look and feel throughout a user interface adds value to
+your product. Streamlining the graphic style will also make the UI seem more
+professional to the user.</p>
+
+<p>This document shows you how to create icons for various parts
+of your application’s user interface that fit the style set by the Android UI
+team. Following these guidelines will help you to create a polished and unified
+experience for the user.</p>
+
+<p>To get started creating conforming icons more quickly, you can download 
+the Android Icon Templates Pack. For more information, see 
+<a href="#templatespack">Using the Android Icon Template Pack</a>.</p>
+
+<h2 id="launcherstructure">Launcher icon</h2>
+
+<p>A launcher icon is the graphic that represents your application on an Android
+device’s Home screen. It is a simplified 3D icon with a fixed perspective. The
+required perspective is shown in Figure 1.</p>
+
+<h4 id="launcherstructure">Structure</h4>
+
+<ul>
+<li>The base of a launcher icon can face either the top view or the front
+view.</li>
+
+<li>The majority of a launcher icon’s surface should be created using the
+launcher icon <a href="#launcherpalette">color palette</a>. To add emphasis, use
+one or more bright accent colors to highlight specific characteristics.</li>
+
+<li>All launcher icons must be created with rounded corners to make them look
+friendly and simple—as shown in Figure 2.</li>
+
+<li>All dimensions specified are based on a 250x250 pixel artboard size
+in a vector graphics editor like Adobe Illustrator, where the icon fits within
+the artboard boundaries.</li>
+
+<li><strong>Final art must be scaled down and exported as a transparent 48x48 px
+PNG file using a raster image editor such as Adobe Photoshop.</strong></li>
+
+<li>Templates for creating launcher icons in Adobe Illustrator and Photoshop are
+available in the Icon Templates Pack.</li>
+</ul>
+
+<table class="image-caption">
+<tr>
+<td class="image-caption-i" style="padding-right:0">
+  <img src="{@docRoot}images/icon_design/launcher_structure.png" alt="A view of
+launcher icon corners and perspective angles" />
+</td>
+<td class="image-caption-c">
+  <div class="caption grad-rule-top">
+    <p><strong>Figure 1.</strong> Perspective angles for launcher icons (90° is
+vertical).</p>
+    <div class="image-caption-nested">
+      <table style="margin-top:0;">
+      <tr><td style="padding-right:1em"><em>1.</em></td><td>92°</td></tr>
+      <tr><td><em>2.</em></td><td>92°</td></tr>
+      <tr><td><em>3.</em></td><td>173°</td></tr>
+      <tr><td><em>4.</em></td><td>171°</td></tr>
+      <tr><td><em>5.</em></td><td>49°</td></tr>
+      <tr><td><em>6.</em></td><td>171°</td></tr>
+      <tr><td><em>7.</em></td><td>64°</td></tr>
+      <tr><td><em>8.</em></td><td>97°</td></tr>
+      <tr><td><em>9.</em></td><td>75°</td></tr>
+      <tr><td><em>10.</em></td><td>93°</td></tr>
+      <tr><td><em>11.</em></td><td>169°</td></tr>
+      </table>
+    </div>
+  </div>
+  <div class="caption grad-rule-top">
+    <p><strong>Figure 2.</strong> Rounded corners for launcher icons.</p>
+  </div>
+</td>
+</tr>
+</table>
+
+<h4 id="launcherlight">Light, effects, and shadows</h4>
+
+<p>Launcher icons are simplified 3D icons using light and shadows for
+definition. A light source is placed slightly to the left in front of the icon,
+and therefore the shadow expands to the right and back.</p>
+
+<table class="image-caption">
+<tr>
+<td class="image-caption-i">
+  <img src="{@docRoot}images/icon_design/launcher_light.png" alt="A view of
+light, effects, and shadows for launcher icons."/>
+</td>
+<td class="image-caption-c">
+  <div class="caption grad-rule-top">
+    <p><strong>Figure 3. </strong>Light, effects, and shadows for launcher icons.</p>
+    <div class="image-caption-nested">
+    <table style="margin-top:0;">
+    <tr><td style="padding-right:1em"><em>1.</em></td><td>Edge highlight:</td><td>white</td></tr>
+    <tr><td><em>2.</em></td><td>Icon shadow:</td><td>black | 20px blur<br>50% opacity | angle 67°</td></tr>
+    <tr><td><em>3.</em></td><td>Front part:</td><td>Use light gradient from color palette</td></tr>
+    <tr><td><em>4.</em></td><td>Detail shadow:</td><td>black | 10px blur<br>75% opacity</td></tr>
+    <tr><td><em>5.</em></td><td> Side part:</td><td>Use medium gradient from color palette</td></tr>
+    </table>
+    </div>
+  </div>
+</td>
+</tr>
+</table>
+
+<table style="margin:0px;padding:0px;">
+<tr>
+<td style="border:0;width:350px;">
+
+<h4 id="launcherpalette">Launcher icon color palette</h4>
+
+<table style="margin:0px;padding:0px;">
+<tr>
+<td class="image-caption-i"><img src="{@docRoot}images/icon_design/launcher_palette_white.png" alt="Color palette, white" style="margin:.5em 0 0 0;" /></td>
+<td class="image-caption-c" style="padding-top:.5em;">White<br>r 0 | g 0 | b 0<br>Used for highlights on edges.</td>
+</tr>
+
+<tr>
+<td class="image-caption-i"><img src="{@docRoot}images/icon_design/launcher_palette_gradient_light.png" alt="Color palette, light gradient" style="margin:.5em 0 0 0;" /></td>
+<td class="image-caption-c" style="padding-top:.5em;">Light gradient<br><em>1:&nbsp;&nbsp;</em>r 0  | g 0  | b 0<br><em>2:&nbsp;&nbsp;</em>r 217 | g 217 | b 217<br>Used on the front (lit) part of the icon.</td>
+</tr>
+
+<tr>
+<td class="image-caption-i"><img src="{@docRoot}images/icon_design/launcher_palette_gradient_medium.png" alt="Color palette, medium gradien" style="margin:.5em 0 0 0;" /></td>
+<td class="image-caption-c" style="padding-top:.5em;">Medium gradient<br><em>1:&nbsp;&nbsp;</em>r 190 | g 190 | b 190<br><em>2:&nbsp;&nbsp;</em>r 115 | g 115 | b 115<br>Used on the side (shaded) part of the icon.</td>
+</tr>
+
+<tr>
+<td class="image-caption-i"><img src="{@docRoot}images/icon_design/launcher_palette_gradient_dark.png" alt="Color palette, dark gradient" style="margin:.5em 0 0 0;" /></td>
+<td class="image-caption-c" style="padding-top:.5em;">Dark gradient<br><em>1:&nbsp;&nbsp;</em>r 100 | g 100 | b 100<br><em>2:&nbsp;&nbsp;</em>r 25  | g 25  | b 25<br>Used on details and parts in the shade of the icon.</td>
+</tr>
+
+<tr>
+<td class="image-caption-i"><img src="{@docRoot}images/icon_design/launcher_palette_black.png" alt="Color palette, black" style="margin:.5em 0 0 0;" /></td>
+<td class="image-caption-c" style="padding-top:.5em;">Black<br>r 255 | g 255 | b 255<br>Used as base color in shadows.</td>
+</tr>
+
+</table>
+
+</td>
+
+<td style="border:0;width:350px">
+
+<h4 id="launchersteps">Step by step</h4>
+
+<ol>
+  <li>Create the basic shapes with a tool like Adobe Illustrator, using the
+angles described in <a href="#launcherstructure">Launcher icon: structure</a>.
+The shapes and effects must fit within a 250x250 pixel artboard.</li>
+  <li>Add depth to shapes by extruding them and create the rounded corners as
+described for the launcher icon structure.</li>
+  <li>Add details and colors. Gradients should be treated as if there is a light
+source placed slightly to the left in front of the icon.</li>
+  <li>Create the shadows with the correct angle and blur effect.</li>
+  <li>Import the icon into a tool like Adobe Photoshop and scale to fit an image
+size of 48x48 px on a transparent background.</li>
+  <li>Export the icon at 48x48 as a PNG file with transparency enabled.</li>
+</ol>
+
+</td>
+</tr>
+</table>
+
+<h2 id="menustructure">Menu icon</h2>
+
+<p>Menu icons are graphical elements placed in the pop-up menu shown to users
+when they press the Menu button. They are drawn in a flat-front perspective.
+Elements in a menu icon must not be visualized in 3D or perspective.</p>
+
+<h4>Structure</h4>
+
+<ul>
+<li>In order to maintain consistency, all menu icons must use the same
+primary palette and the same effects. For more information, see the
+menu icon <a href="#menupalette">color palette</a>. </li>
+
+<li>Menu icons should include rounded corners, but only when logically
+appropriate. For example, in Figure 3 the logical place for rounded corners is
+the roof and not the rest of the building.</span></li>
+
+<li>All dimensions specified on this page are based on a 48x48 pixel artboard 
+size with a 6 pixel safeframe.</li>
+
+<li>The menu icon effect (the outer glow) described in <a
+href="#menulight">Light, effects, and shadows</a> can overlap the 6px safeframe,
+but only when necessary. The base shape must always stay inside the
+safeframe.</li>
+
+<li><strong>Final art must be exported as a transparent PNG file.</strong></li>
+
+<li>Templates for creating menu icons in Adobe Photoshop are available in the 
+Icon Templates Pack.</li>
+</ul>
+
+<table class="image-caption">
+<tr>
+<td class="image-caption-i" style="padding-right:0">
+  <img src="{@docRoot}images/icon_design/menu_structure.png" alt="A view of menu
+icon structure." />
+</td>
+<td class="image-caption-c">
+  <div class="caption grad-rule-top">
+    <p><strong>Figure 4. </strong>Safeframe and corner-rounding for menu
+icons. Icon size is 48x48.</p>
+  </div>
+</td>
+</tr>
+</table>
+
+
+<h4 id="menulight">Light, effects, and shadows</h4>
+
+<p>Menu icons are flat and pictured face on. A slight deboss and some other
+effects, which are shown below, are used to create depth.</p>
+
+<table class="image-caption">
+<tr>
+<td class="image-caption-i">
+  <img src="{@docRoot}images/icon_design/menu_light.png" alt="A view of light, effects, and shadows for launcher icons."/>
+</td>
+<td class="image-caption-c">
+  <div class="caption grad-rule-top">
+    <p><strong>Figure 5. </strong>Light, effects, and shadows for launcher icons.</p>
+    <div class="image-caption-nested">
+    <table style="margin-top:0;">
+    <tr><td style="padding-right:1em"><em>1.</em></td><td>Front part:</td><td>Use fill gradient from primary color palette</td></tr>
+    <tr><td><em>2.</em></td><td>Inner shadow:</td><td>black | 20 % opacity<br>angle 90° | distance 2px<br>size 2px</td></tr>
+    <tr><td><em>3.</em></td><td>Outer glow:</td><td>white | 55% opacity <br>spread 10% | size 3px</td></tr>
+    <tr><td><em>5.</em></td><td>Inner bevel:</td><td>depth 1% | direction down size 0px<br>angle 90° | altitude 10°<br>highlight white 70% opacity<br>shadow black 25% opacity</td></tr>
+    </table>
+    </div>
+  </div>
+</td>
+</tr>
+</table>
+
+<table style="margin:0px;padding:0px;">
+<tr>
+<td style="border:0;width:350px;">
+
+<h4 id="menupalette">Color palette</h4>
+
+<table style="margin:0px;padding:0px;">
+<tr>
+<td class="image-caption-i"><img src="{@docRoot}images/icon_design/menu_palette_white.png" alt="Color palette, white" style="margin:.5em 0 0 0;" /></td>
+<td class="image-caption-c" style="padding-top:.5em;">White<br>r 0 | g 0 | b 0<br>Used for outer glow and bevel highlight.</td>
+</tr>
+
+<tr>
+<td class="image-caption-i"><img src="{@docRoot}images/icon_design/menu_palette_gradient_medium.png" alt="Color palette, medium gradient" style="margin:.5em 0 0 0;" /></td>
+<td class="image-caption-c" style="padding-top:.5em;">Fill gradient<br><em>1:&nbsp;&nbsp;</em>r 163 | g 163 | b 163<br><em>2:&nbsp;&nbsp;</em>r 120 | g 120 | b 120<br>Used as color fill.</td>
+</tr>
+
+<tr>
+<td class="image-caption-i"><img src="{@docRoot}images/icon_design/menu_palette_black.png" alt="Color palette, black" style="margin:.5em 0 0 0;" /></td>
+<td class="image-caption-c" style="padding-top:.5em;">Black<br>r 255 | g 255 | b 255<br>Used for inner shadow and bevel shadow.</td>
+</tr>
+
+</table>
+
+</td>
+
+<td style="border:0;width:350px">
+
+<h4 id="menusteps">Step by step</h4>
+
+<ol>
+<li>Create the basic shapes using a tool like Adobe Illustrator.</li>
+<li>Import the shape into a tool like Adobe Photoshop and scale to fit an image
+of 48x48 px on a transparent background. Mind the safeframe.</li>
+<li>Add the effects seen as described in Figure 5.</li>
+<li>Export the icon at 48x48 as a PNG file with transparency enabled.</li>
+</ol>
+
+</td>
+</tr>
+</table>
+
+
+<h2 id="statusbarstructure">Status bar icon</h2>
+
+<p>Status bar icons are used to represent notifications from your application in
+the status bar. Graphically, they are very similar to menu icons, but are
+smaller and higher in contrast.</p>
+
+<h4>Structure</h4>
+
+<ul>
+<li>Rounded corners must always be applied to the base shape and to the details
+of a status bar icon shown Figure 7.</li>
+
+<li>All dimensions specified are based on a 25x25 pixel artboard size with a 2
+pixel safeframe.</li>
+
+<li>Status bar icons can overlap the safeframe to the left and right when
+necessary, but must not overlap the safeframe at the top and bottom.</li>
+
+<li><strong>Final art must be exported as a transparent PNG file.</strong></li>
+
+<li>Templates for creating status bar icons using Adobe Photoshop are available
+in the Icon Templates Pack.</li>
+</ul>
+
+<table class="image-caption">
+<tr>
+<td class="image-caption-i" style="padding-right:0">
+  <img src="{@docRoot}images/icon_design/statusbar_structure.png" alt="A view of
+status bar icon structure." />
+</td>
+<td class="image-caption-c">
+  <div class="caption grad-rule-top">
+    <p><strong>Figure 6. </strong>Safeframe and corner-rounding for status bar
+icons. Icon size is 25x25.</p>
+  </div>
+</td>
+</tr>
+</table>
+
+
+<h4 id="statusbarlight">Light, effects, and shadows</h4>
+
+<p>Status bar icons are slightly debossed, high in contrast, and pictured
+face-on to enhance clarity at small sizes.</p>
+
+<table class="image-caption">
+<tr>
+<td class="image-caption-i">
+  <img src="{@docRoot}images/icon_design/statusbar_light.png" alt="A view of
+light, effects, and shadows for launcher icons."/>
+</td>
+<td class="image-caption-c">
+  <div class="caption grad-rule-top">
+    <p><strong>Figure 7. </strong>Light, effects, and shadows for launcher icons.</p>
+    <div class="image-caption-nested">
+    <table style="margin-top:0;">
+    <tr><td style="padding-right:1em"><em>1.</em></td><td>Front part:</td><td>Use fill gradient from primary color palette</td></tr>
+    <tr><td><em>2.</em></td><td>Inner bevel:</td><td>depth 100% | direction down<br>size 0px | angle 90° |<br>altitude 30°<br>highlight white 75% opacity<br>shadow black 75% opacity</td></tr>
+    <tr><td><em>3.</em></td><td>Detail:</td><td>white</td></tr>
+    <tr><td><em>4.</em></td><td>Disabled detail:</td><td>grey gradient from palette<br>+ inner bevel: smooth | depth 1% | direction down | size 0px | angle 117° | <br>altitude 42° | highlight white 70% | no shadow</td></tr>
+    </table>
+    </div>
+  </div>
+</td>
+</tr>
+</table>
+
+<table style="margin:0px;padding:0px;">
+<tr>
+<td style="border:0;width:350px;">
+
+<h4 id="menupalette">Color palette</h4>
+
+<p>Only status bar icons related to the phone function use full color; all other status bar icons should remain monochromatic.</p>
+
+<table style="margin:0px;padding:0px;">
+<tr>
+<td class="image-caption-i"><img src="{@docRoot}images/icon_design/statusbar_palette_white.png" alt="Color palette, white" style="margin:.5em 0 0 0;" /></td>
+<td class="image-caption-c" style="padding-top:.5em;">White<br>r 0 | g 0 | b 0<br>Used for details within the icons and bevel highlight.</td>
+</tr>
+
+<tr>
+<td class="image-caption-i"><img src="{@docRoot}images/icon_design/statusbar_palette_fill.png" alt="Color palette, grey gradient" style="margin:.5em 0 0 0;" /></td>
+<td class="image-caption-c" style="padding-top:.5em;">Grey gradient<br><em>1:&nbsp;&nbsp;</em>r 169 | g 169 | b 169<br><em>2:&nbsp;&nbsp;</em>r 126 | g 126 | b 126<br>Used for disabled details within the icon.</td>
+</tr>
+
+<tr>
+<td class="image-caption-i"><img src="{@docRoot}images/icon_design/statusbar_palette_grey.png" alt="Color palette, fill gradient" style="margin:.5em 0 0 0;" /></td>
+<td class="image-caption-c" style="padding-top:.5em;">Fill gradient<br><em>1:&nbsp;&nbsp;</em>1 r 105 | g 105 | b 105<br><em>2:&nbsp;&nbsp;</em>r 10   | g 10   | b 10<br>Used as color fill.</td>
+</tr>
+
+<tr>
+<td class="image-caption-i"><img src="{@docRoot}images/icon_design/statusbar_palette_black.png" alt="Color palette, black" style="margin:.5em 0 0 0;" /></td>
+<td class="image-caption-c" style="padding-top:.5em;">Black<br>r 255 | g 255 | b 255<br>Used for bevel shadow.</td>
+</tr>
+
+</table>
+
+</td>
+
+<td style="border:0;width:350px">
+
+<h4 id="menusteps">Step by step</h4>
+
+<ol>
+<li>In a tool like Adobe Photoshop, create the base shape within a 25x25 px
+image on a transparent background. Mind the safeframe, and keep the upper and
+lower 2 pixels free.</li>
+<li>Add rounded corners as specified in Figure 6.</li>
+<li>Add light, effects, and shadows as specified in Figure 7.</li>
+<li>Export the icon at 25x25 as a PNG file with transparency enabled.</li>
+</ol>
+
+</td>
+</tr>
+</table>
+
+
+<h2 id="tabstructure">Tab icon</h2>
+
+<p>Tab icons are graphical elements used to represent individual tabs in a
+multi-tab interface. Each tab icon has two states: unselected and selected.</p>
+
+<h4>Structure</h4>
+
+<ul>
+<li>Unselected tab icons have the same fill gradient and effects as menu icons,
+but with no outer glow.</li>
+
+<li>Selected tab icons look just like unselected tab icons, but with a fainter
+inner shadow, and have the same front part gradient as dialog icons.</li>
+
+<li>Tab icons have a 1 px safeframe which should only be overlapped for the edge
+of the anti-alias of a round shape.</li>
+
+<li>All dimensions specified on this page are based on a 32x32 px artboard size.
+Keep 1 px of padding around the bounding box inside the Photoshop template.</li>
+
+<li><strong>Final art must be exported as a 32x32 px transparent PNG
+file.</strong></li>
+
+<li>Templates for creating tab icons in Adobe Photoshop are available in the
+Icon Templates Pack.</li>
+</ul>
+
+<table class="image-caption">
+<tr>
+<td class="image-caption-i" style="padding-right:0">
+  <img src="{@docRoot}images/icon_design/tab_icon_unselected.png" alt="A view of
+unselected tab icon structure." />
+</td>
+<td class="image-caption-c">
+  <div class="caption grad-rule-top">
+    <p><strong>Figure 8. </strong>Safeframe and fill gradient for unselected tab
+icons. Icon size is 32x32.</p>
+  </div>
+</td>
+</tr>
+<tr>
+<td class="image-caption-i" style="padding-right:0">
+  <img src="{@docRoot}images/icon_design/tab_icon_selected.png" alt="A view of
+selected tab icon structure." />
+</td>
+<td class="image-caption-c">
+  <div class="caption grad-rule-top">
+    <p><strong>Figure 9. </strong>Safeframe and fill gradient for tab icons in
+selected state. Icon size is 32x32.</p>
+  </div>
+</td>
+</tr>
+</table>
+
+<h3 id="unselectedtabdetails">Unselected tab icon</h3>
+
+<h4 id="unselectedtablight">Light, effects, and shadows</h4>
+
+<p>Unselected tab icons look just like the selected tab icons, but with a
+fainter inner shadow, and the same front part gradient as the dialog icons.</p>
+
+<table class="image-caption">
+<tr>
+<td class="image-caption-i">
+  <img src="{@docRoot}images/icon_design/tab_unselected_light.png" alt="A view
+of light, effects, and shadows for unselected tab icons."/>
+</td>
+<td class="image-caption-c">
+  <div class="caption grad-rule-top">
+    <p><strong>Figure 10. </strong>Light, effects, and shadows for unselected
+tab icons.</p>
+    <div class="image-caption-nested">
+    <table style="margin-top:0;">
+    <tr><td style="padding-right:1em"><em>1.</em></td><td>Front part:</td><td>gradient overlay | angle 90°<br>bottom color: r 223 | g 223 | b 223<br>top color: r 249 | g 249 | b 249<br>bottom color location: 0%<br>top color location: 75%</td></tr>
+    <tr><td><em>2.</em></td><td>Inner shadow:</td><td>black | 10 % opacity | angle 90° distance 2px | size 2px</td></tr>
+    <tr><td><em>3.</em></td><td>Inner bevel:</td><td>depth 1% | direction down | size 0px | angle 90° | altitude 10°<br>highlight white 70% opacity<br>shadow black 25% opacity</td></tr>
+    </table>
+    </div>
+  </div>
+</td>
+</tr>
+</table>
+
+
+<table style="margin:0px;padding:0px;">
+<tr>
+<td style="border:0;width:350px;">
+
+<h4 id="menusteps">Step by step</h4>
+
+<ol>
+<li>Create the basic shapes using a tool like Adobe Illustrator.</li>
+<li>Import the shape to a tool like Adobe Photoshop and scale to fit an image of
+32x32 px on a transparent background.</li>
+<li>Add the effects seen in Figure 10 for the unselected state filter.</li>
+<li>Export the icon at 32x32 as a PNG file with transparency enabled.</li>
+</ol>
+
+</td>
+</tr>
+</table>
+
+<h3 id="selectedtabdetails">Selected tab icon</h3>
+
+<p>The selected tab icons have the same fill gradient and effects as the menu
+icon, but with no outer glow.</p>
+
+<table class="image-caption">
+<tr>
+<td class="image-caption-i">
+  <img src="{@docRoot}images/icon_design/tab_selected_light.png" alt="A view of
+light, effects, and shadows for selected tab icons."/>
+</td>
+<td class="image-caption-c">
+  <div class="caption grad-rule-top">
+    <p><strong>Figure 11. </strong>Light, effects, and shadows for selected tab
+icons.</p>
+    <div class="image-caption-nested">
+    <table style="margin-top:0;">
+    <tr><td style="padding-right:1em"><em>1.</em></td><td>Front part:</td><td>Use fill gradient from color palette.</td></tr>
+    <tr><td><em>2.</em></td><td>Inner shadow:</td><td>black | 20% opacity | <br>angle 90° | distance 2px | <br>size 2px</td></tr>
+    <tr><td><em>3.</em></td><td>Inner bevel:</td><td>depth 1% | direction down | size 0px | angle 90° | <br>altitude 10°<br>highlight white 70% opacity<br>shadow black 25% opacity</td></tr>
+    </table>
+    </div>
+  </div>
+</td>
+</tr>
+</table>
+
+<table style="margin:0px;padding:0px;">
+<tr>
+<td style="border:0;width:350px;">
+
+<h4 id="menupalette">Color palette</h4>
+
+<table style="margin:0px;padding:0px;">
+<tr>
+<td class="image-caption-i"><img src="{@docRoot}images/icon_design/menu_palette_gradient_medium.png" alt="Color palette, fill gradient" style="margin:.5em 0 0 0;" /></td>
+<td class="image-caption-c" style="padding-top:.5em;">Fill gradient<br><em>1:&nbsp;&nbsp;</em>r 163 | g 163 | b 163<br><em>2:&nbsp;&nbsp;</em>r 120 | g 120 | b 120<br>Used as color fill on unselected tab icons.</td>
+</tr>
+
+</table>
+
+</td>
+
+<td style="border:0;width:350px">
+
+<h4 id="menusteps">Step by step</h4>
+
+<ol>
+<li>Create the basic shape using a tool like Adobe Illustrator.</li>
+<li>Import the shape into a tool like Adobe Photoshop and scale to fit a 32x32
+px artboard with a transparent background. </li>
+<li>Add the effects seen in Figure 11 for the selected state filter.</li>
+<li>Export the icon at 32x32 as a PNG file with transparency enabled.</li>
+</ol>
+
+</td>
+</tr>
+</table>
+
+
+<h2 id="dialogstructure">Dialog icon</h2>
+
+<p>Dialog icons are shown in pop-up dialog boxes that prompt the user for
+interaction. They use a light gradient and inner
+shadow in order to stand out against a dark background.</p>
+
+<h4>Structure</h4>
+
+<ul>
+<li>Dialog icons have a 1 pixel safeframe. The base shape must fit within the
+safeframe, but the anti-alias of a round shape can overlap the safeframe. <span
+class="body-copy"></li>
+
+<li>All dimensions specified on this page are based on a 32x32 pixel artboard size
+in Adobe Photoshop. Keep 1 pixel of padding around the bounding box inside the
+Photoshop template.</li>
+
+<li><strong>Final art must be exported as a transparent PNG file.</strong></li>
+
+<li>Templates for creating dialog icons in Adobe Photoshop are available in the
+Icon Templates Pack.</li>
+</ul>
+
+<table class="image-caption">
+<tr>
+<td class="image-caption-i" style="padding-right:0">
+  <img src="{@docRoot}images/icon_design/dialog_icon.png" alt="A view of dialog
+icon structure." />
+</td>
+<td class="image-caption-c">
+  <div class="caption grad-rule-top">
+    <p><strong>Figure 12. </strong>Safeframe and fill gradient for dialog icons.
+Icon size is 32x32.</p>
+  </div>
+</td>
+</tr>
+</table>
+
+
+<h4 id="dialoglight">Light, effects, and shadows</h4>
+
+<p>Dialog icons are flat and pictured face-on. In order to stand out against a
+dark background, they are built up using a light gradient and inner shadow.</p>
+
+<table class="image-caption">
+<tr>
+<td class="image-caption-i">
+  <img src="{@docRoot}images/icon_design/dialog_light.png" alt="A view of light,
+effects, and shadows for dialog icons."/>
+</td>
+<td class="image-caption-c">
+  <div class="caption grad-rule-top">
+    <p><strong>Figure 13. </strong>Light, effects, and shadows for dialog
+icons.</p>
+    <div class="image-caption-nested">
+    <table style="margin-top:0;">
+    <tr><td style="padding-right:1em"><em>1.</em></td><td>Front part:</td><td>gradient overlay | angle 90°<br>bottom: r 223 | g 223 | b 223<br>top: r 249 | g 249 | b 249<br>bottom color location: 0%<br>top color location: 75%</td></tr>
+    <tr><td><em>2.</em></td><td>Inner shadow:</td><td>black | 25% opacity | <br>angle -90° | distance 1px | size 0px</td></tr>
+    </table>
+    </div>
+  </div>
+</td>
+</tr>
+</table>
+
+
+<table style="margin:0px;padding:0px;">
+<tr>
+<td style="border:0;width:350px;">
+
+<h4 id="menusteps">Step by step</h4>
+
+<ol>
+<li>Create the basic shapes using a tool like Adobe Illustrator.</li>
+<li>Import the shape into a tool like Adobe Photoshop and scale to fit an image
+of 32x32 px on a transparent background. </li>
+<li>Add the effects seen in Figure 13 for the proper filter.</li>
+<li>Export the icon at 32x32 as a PNG file with transparency enabled.</li>
+</ol>
+
+</td>
+</tr>
+</table>
+
+
+<h2 id="listviewstructure">List view icon</h2>
+
+<p>List view icons look a lot like dialog icons, but they use an inner shadow
+effect where the light source is above the object. They are also designed to be
+used only in a list view. Examples include the Android Market application home
+screen and the driving directions screen in the Maps application.</p>
+
+<h4>Structure</h4>
+
+<ul>
+<li>A list view icon normally has a 1 px safeframe, but it is OK to use the
+safeframe area for the edge of the anti-alias of a round shape. </li>
+
+<li>All dimensions specified are based on a 32x32 pixel artboard size in
+Photoshop. Keep 1 pixel of padding around the bounding box inside the template.
+ </li>
+
+<li><strong>Final art must be exported as a transparent PNG file.</strong></li>
+
+<li>Templates for creating list view icons in Adobe Photoshop are available in
+the Icon Templates Pack. </li>
+</ul>
+
+<table class="image-caption">
+<tr>
+<td class="image-caption-i" style="padding-right:0">
+  <img src="{@docRoot}images/icon_design/listview_icon.png" alt="A view of list
+view icon structure." />
+</td>
+<td class="image-caption-c">
+  <div class="caption grad-rule-top">
+    <p><strong>Figure 14. </strong>Safeframe and fill gradient for list view
+icons. Icon size is 32x32.</p>
+  </div>
+</td>
+</tr>
+</table>
+
+<h4 id="listviewlight">Light, effects, and shadows</h4>
+
+<p>List view icons are flat and pictured face-on with an inner shadow. Built up
+by a light gradient and inner shadow, they stand out well on a dark
+background.</p>
+
+<table class="image-caption">
+<tr>
+<td class="image-caption-i">
+  <img src="{@docRoot}images/icon_design/listview_icon_details.png" alt="A view
+of light, effects, and shadows for list view icons."/>
+</td>
+<td class="image-caption-c">
+  <div class="caption grad-rule-top">
+    <p><strong>Figure 15. </strong>Light, effects, and shadows for list view
+icons.</p>
+    <div class="image-caption-nested">
+    <table style="margin-top:0;">
+    <tr><td style="padding-right:1em"><em>1.</em></td><td>Inner shadow:</td><td>black | 57 % opacity | angle 120° | blend mode normal | distance 1px | size 1px <td></tr>
+    <tr><td><em>2.</em></td><td>Background:</td><td>black | standard system color <br>These icons are displayed in list views only.</td></tr>
+    <tr><td colspan="2">Note: The list view icon sits on 32x32 px artboard in Photoshop, without a safeframe.</td></tr>
+    </table>
+    </div>
+  </div>
+</td>
+</tr>
+</table>
+
+<table style="margin:0px;padding:0px;">
+<tr>
+<td style="border:0;width:350px;">
+
+<h4 id="menusteps">Step by step</h4>
+
+<ol>
+<li>Add the effects seen in Figure 15 for the proper filter.</li>
+<li>Export the icon at 32x32 as a PNG file with transparency enabled.</li>
+<li>Create the basic shapes using a tool like Adobe Illustrator.</li>
+<li>Import the shape into a tool like Adobe Photoshop and scale to fit an image
+of 32x32 px on a transparent background. </li>
+</ol>
+
+</td>
+</tr>
+</table>
+
+
+<h2 id="dodonts">General guidelines</h2>
+
+<p>Below are some "do and don't" guidelines to consider when creating icons for
+your application. By following the guidelines, you can ensure that your icons
+will work well with other parts of the Android platform UI and will meet the
+expectations of your application's users. </p>
+
+<table style="margin:0px;padding:0px;">
+<tr>
+<td style="border:0;width:350px;">
+
+<h4>Do...</h4>
+
+<ul>
+<li>Use a normal perspective. The depth of an object should be realistic.</li>
+<li>Keep it simple! By overdoing an icon, it loses it purpose and
+readability.</li>
+<li>Use colors only when necessary. Mind that the base of a launcher icon should
+be grey and feel solid. </li>
+<li>Use the correct angles for the specific icon types.</li>
+</ul>
+</td>
+<td style="border:0;width:350px;">
+
+<h4>Don’t...</h4>
+
+<ul>
+<li>Use open elements like text alone as icons. Instead place those elements on
+a base shape.</li>
+<li>Use colors for your status bar notifications. Those are reserved for
+specific phone-only functions.</li>
+</ul>
+</td>
+</tr>
+<tr>
+<td colspan="2" style="border:0;">
+<img src="{@docRoot}images/icon_design/do_dont.png" alt="Side-by-side examples
+of good/bad icon design."/>
+</td>
+</table>
+
+<h2 id="templatespack">Using the Android Icon Templates Pack</h2>
+
+<p>The Android Icon Templates Pack is a collection of template designs, filters,
+and settings that make it easier for you to create icons that conform to the
+general specifications given in this document. We recommend downloading the
+template pack archive before you get started with your icon design.</p>
+
+<p>The icon templates are provided in Adobe Photoshop and Adobe Illustrator file
+formats, which preserves the layers and design treatments we used when creating the
+standard icons for the Android platform. You can load the template files into any 
+compatible image-editing program, although your ability to work directly with the 
+layers and treatments may vary based on the program you are using.</p>
+
+<p>You can obtain the Icon Templates Pack archive using the link below: </p>
+
+<p style="margin-left:2em"><a
+href="{@docRoot}shareables/icon_templates-v1.0.zip">Download the Icon Templates
+Pack &raquo;</a>
+
+
+<h2 id="iconappendix">Icon appendix</p>
+
+<h3 id="launcherapx">Standard launcher icons</h3>
+
+<p>Shown below are examples of launcher icons used by Android applications. The
+icons are provided for your reference only &mdash; please do not reuse these
+icons in your applications.</code>.
+
+<table class="image-caption">
+<tr>
+
+<td class="image-caption-i image-list">
+  <img src="/images/icon_design/ic_launcher_alarmclock.png" alt="Android asset" />
+  <div class="caption">Alarm Clock</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="/images/icon_design/ic_launcher_browser.png" alt="Android asset" />
+  <div class="caption">Browser</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="/images/icon_design/ic_launcher_calculator.png" alt="Android asset" />
+  <div class="caption">Calculator</div></td>
+	
+
+<td class="image-caption-i image-list">
+  <img src="/images/icon_design/ic_launcher_calendar.png" alt="Android asset" />
+  <div class="caption">Calendar</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="/images/icon_design/ic_launcher_video_camera.png" alt="Android asset" />
+  <div class="caption">Camcorder</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="/images/icon_design/ic_launcher_camera.png" alt="Android asset" />
+  <div class="caption">Camera</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="/images/icon_design/ic_launcher_contacts.png" alt="Android asset" />
+  <div class="caption">Contacts</div></td>
+
+</tr>
+<tr>
+
+<td class="image-caption-i image-list">
+  <img src="/images/icon_design/ic_launcher_phone_dialer.png" alt="Android asset" />
+  <div class="caption">Dialer</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="/images/icon_design/ic_launcher_email_generic.png" alt="Android asset" />
+  <div class="caption">Email</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="/images/icon_design/ic_launcher_gallery.png" alt="Android asset" />
+  <div class="caption">Gallery</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="/images/icon_design/ic_launcher_generic_application.png" alt="Android asset" />
+  <div class="caption">Generic application</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="/images/icon_design/ic_launcher_email.png" alt="Android asset" />
+  <div class="caption">Gmail</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="/images/icon_design/ic_launcher_google_talk.png" alt="Android asset" />
+  <div class="caption">Google Talk</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="/images/icon_design/ic_launcher_IM.png" alt="Android asset" />
+  <div class="caption">IM</div></td>
+
+</tr>
+<tr>
+
+<td class="image-caption-i image-list">
+  <img src="/images/icon_design/ic_launcher_maps.png" alt="Android asset" />
+  <div class="caption">Maps</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="/images/icon_design/ic_launcher_marketplace.png" alt="Android asset" />
+  <div class="caption">Market </div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="/images/icon_design/ic_launcher_sms_mms.png" alt="Android asset" />
+  <div class="caption">Messaging </div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="/images/icon_design/ic_launcher_musicplayer_2.png" alt="Android asset" />
+  <div class="caption">Music</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="/images/icon_design/ic_launcher_settings.png" alt="Android asset" />
+  <div class="caption">Settings</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="/images/icon_design/ic_launcher_voicedial.png" alt="Android asset" />
+  <div class="caption">Voice Dialer</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="/images/icon_design/ic_launcher_voicesearch.png" alt="Android asset" />
+  <div class="caption">Voice Search</div></td>
+
+</tr>
+<tr>
+
+<td class="image-caption-i image-list">
+  <img src="/images/icon_design/ic_launcher_youtube.png" alt="Android asset" />
+  <div class="caption">YouTube</div></td>
+</tr>
+</table>
+
+<h3 id="menuapx">Standard menu icons</h3>
+
+<p>Shown below are standard menu icons that are included in the Android platform
+(as of Android 1.5). You can reference any of these icon resources from your
+application as needed, but make sure that the action you assign to the icon is
+consistent with that listed. Note that this is not a complete list of icons and
+that the actual appearance of standard icons may change across platform
+versions.</p>
+
+<p>To reference one of the icons from your code, use
+<code>android.R.drawable.&lt;icon_resource_identifier&gt;</code>. For example,
+you can call a menu item's {@link android.view.MenuItem#setIcon(android.graphics.drawable.Drawable) setIcon()}
+method and pass the resource name:</p> 
+
+<p style="margin-left:2em"><code>.setIcon(android.R.drawable.ic_menu_more);</code>.
+
+<p>You could reference the same icon from a layout file using
+<code>android:icon="@android:drawable/ic_menu_more"></code>.</p>
+
+<p>To determine the resource ID for an icon listed below, hover over the icon or
+simply look at image filenames, which use the format
+"&lt;icon_resource_identifier&gt;.png".</p>
+
+<table class="image-caption">
+<tr>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_add.png" title="ic_menu_add" alt="Android asset" />
+  <div class="caption">Add</div></td>
+	
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_archive.png" title="ic_menu_archive" alt="Android asset" />
+  <div class="caption">Archive</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_attachment.png" title="ic_menu_attachment" alt="Android asset" />
+  <div class="caption">Attach</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_back.png" title="ic_menu_back" alt="Android asset" />
+  <div class="caption">Back</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_call.png" title="ic_menu_call" alt="Android asset" />
+  <div class="caption">Call</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_camera.png" title="ic_menu_camera" alt="Android asset" />
+  <div class="caption">Camera</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_close_clear_cancel.png" title="ic_menu_close_clear_cancel" alt="Android asset" />
+  <div class="caption">Clear / Close / Cancel / Discard </div></td>
+
+</tr>
+<tr>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_compass.png" title="ic_menu_compass" alt="Android asset" />
+  <div class="caption">Compass</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_delete.png" title="ic_menu_delete" alt="Android asset" />
+  <div class="caption">Delete</div></td>
+	
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_directions.png" title="ic_menu_directions" alt="Android asset" />
+  <div class="caption">Directions</div></td>
+	
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_edit.png" title="ic_menu_edit" alt="Android asset" />
+  <div class="caption">Edit</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_favorite.png" title="ic_menu_favorite" alt="Android asset" />
+  <div class="caption">Favorite</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_forward.png" title="ic_menu_forward" alt="Android asset" />
+  <div class="caption">Forward</div></td>
+	
+
+<td class="image-caption-i image-list">	
+  <img src="{@docRoot}images/icon_design/ic_menu_gallery.png" title="ic_menu_gallery" alt="Android asset" />
+  <div class="caption">Gallery</div></td>
+
+</tr>
+<tr>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_goto.png" title="ic_menu_goto" alt="Android asset" />
+  <div class="caption">Go to</div></td>
+	
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_help.png" title="ic_menu_help" alt="Android asset" />
+  <div class="caption">Help</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_recent_history.png" title="ic_menu_recent_history" alt="Android asset" />
+  <div class="caption">History</div></td>
+	
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_home.png" title="ic_menu_home" alt="Android asset" />
+  <div class="caption">Home</div></td>
+	
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_info_details.png" title="ic_menu_info_details" alt="Android asset" />
+  <div class="caption">Info / details</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_mapmode.png" title="ic_menu_mapmode" alt="Android asset" />
+  <div class="caption">Map mode</div></td>
+	
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_mark.png" title="ic_menu_mark" alt="Android asset" />
+  <div class="caption">Mark</div></td>
+
+</tr>
+<tr>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_mylocation.png" title="ic_menu_mylocation" alt="Android asset" />
+  <div class="caption">My Location</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_more.png" title="ic_menu_more" alt="Android asset" />
+  <div class="caption">More</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_play_clip.png" title="ic_menu_play_clip" alt="Android asset" />
+  <div class="caption">Play</div></td>
+	
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_preferences.png" title="ic_menu_preferences" alt="Android asset" />
+  <div class="caption">Preferences</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_refresh.png" title="ic_menu_refresh" alt="Android asset" />
+  <div class="caption">Refresh</div></td>
+	
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_rotate.png" title="ic_menu_rotate" alt="Android asset" />
+  <div class="caption">Rotate</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_save.png" title="ic_menu_save" alt="Android asset" />
+  <div class="caption">Save</div></td>
+
+</tr>
+<tr>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_send.png" title="ic_menu_send" alt="Android asset" />
+  <div class="caption">Send</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_search.png" title="ic_menu_search" alt="Android asset" />
+  <div class="caption">Search</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_share.png" title="ic_menu_share" alt="Android asset" />
+  <div class="caption">Share</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_shuffle.png" title="ic_menu_shuffle" alt="Android asset" />
+  <div class="caption">Shuffle</div></td>
+	
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_upload.png" title="ic_menu_upload" alt="Android asset" />
+  <div class="caption">Upload</div></td>
+	
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_view.png" title="ic_menu_view" alt="Android asset" />
+  <div class="caption">View</div></td>
+	
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_camera_video_view.png" title="ic_menu_camera_video_view" alt="Android asset" />
+  <div class="caption">Video</div></td>
+
+</tr>
+<tr>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/ic_menu_zoom.png" title="ic_menu_zoom" alt="Android asset" />
+  <div class="caption">Zoom</div></td>
+
+</tr>
+</table>
+
+
+<h3 id="statusbarapx">Standard status bar icons</h3>
+
+<p>Shown below are standard status bar icons included in the Android platform
+(as of Android 1.5). You can reference any of these icon resources from your
+application as needed, but make sure that the meaning of the icon is consistent
+with the standard meaning listed. Note that this is not a complete list of icons
+and that the actual appearance of standard icons may change across platform
+versions.</p>
+
+<p>To reference one of the icons from your code, use
+<code>android.R.drawable.&lt;icon_resource_identifier&gt;</code>. For example,
+you can construct a simple notification that references one of the icons like
+this: </p>
+
+<p style="margin-left:2em"><code>new Notification(R.drawable.stat_notify_calendar, 
+"sample text", System.currentTimeMillis());</code></p>
+
+<p>To determine the resource ID for an icon listed below, hover over the icon 
+or simply look at the image filename, which use the format 
+"&lt;icon_resource_identifier&gt;.png".</p>
+
+
+<table class="image-caption">
+<tr>
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_sys_data_connected_3g.png" title="stat_sys_data_connected_3g" alt="Android asset" />
+  <div class="caption">3G</div></td>
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_sys_signal_flightmode.png" title="stat_sys_signal_flightmode" alt="Android asset" />
+  <div class="caption">Airplane mode</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_notify_alarm.png" title="stat_notify_alarm" alt="Android asset" />
+  <div class="caption">Alarm</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_sys_data_bluetooth.png" title="stat_sys_data_bluetooth" alt="Android asset" />
+  <div class="caption">Bluetooth</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_sys_data_bluetooth_connected.png" title="stat_sys_data_bluetooth_connected" alt="Android asset" />
+  <div class="caption">Bluetooth connected</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_notify_calendar.png" title="stat_notify_calendar" alt="Android asset" />
+  <div class="caption">Calendar</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_notify_disk_full.png" title="stat_notify_disk_full" alt="Android asset" />
+  <div class="caption">Disk full</div></td>
+
+</tr>
+<tr>
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_sys_data_connected_e.png" title="stat_sys_data_connected_e" alt="Android asset" />
+  <div class="caption">EDGE</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_notify_email_generic.png" title="stat_notify_email_generic" alt="Android asset" />
+  <div class="caption">Email</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_notify_email.png" title="stat_notify_email" alt="Android asset" />
+  <div class="caption">Gmail</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_sys_data_connected_g.png" title="stat_sys_data_connected_g" alt="Android asset" />
+  <div class="caption">GPRS</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_notify_chat.png" title="stat_notify_chat" alt="Android asset" />
+  <div class="caption">IM</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_sys_install_complete.png" title="stat_sys_install_complete" alt="Android asset" />
+  <div class="caption">Installation complete</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_notify_musicplayer.png" title="stat_notify_musicplayer" alt="Android asset" />
+  <div class="caption">Music</div></td>
+
+</tr>
+<tr>
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_sys_r_signal_4.png" title="stat_sys_r_signal_4" alt="Android asset" />
+  <div class="caption">Roaming</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_sys_signal_4.png" title="stat_sys_signal_4" alt="Android asset" />
+  <div class="caption">Signal</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_sys_signal_null.png" title="stat_sys_signal_null" alt="Android asset" />
+  <div class="caption">Signal unavailable</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_sys_ringer_silent_old.png" title="stat_sys_ringer_silent_old" alt="Android asset" />
+  <div class="caption">Silent mode</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_notify_sms.png" title="stat_notify_sms" alt="Android asset" />
+  <div class="caption">SMS/MMS</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_sys_speakerphone.png" title="stat_sys_speakerphone" alt="Android asset" />
+  <div class="caption">Speaker phone</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_notify_sync_anim0.png" title="stat_notify_sync_anim0" alt="Android asset" />
+  <div class="caption">Sync</div></td>
+
+</tr>
+<tr>
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_notify_sync_error.png" title="stat_notify_sync_error" alt="Android asset" />
+  <div class="caption">Sync error</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_sys_data_usb.png" title="stat_sys_data_usb" alt="Android asset" />
+  <div class="caption">USB connected</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_sys_ringer_vibrate.png" title="stat_sys_ringer_vibrate" alt="Android asset" />
+  <div class="caption">Vibrate</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_notify_voicemail.png" title="stat_notify_voicemail" alt="Android asset" />
+  <div class="caption">Voicemail</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_sys_warning.png" title="stat_sys_warning" alt="Android asset" />
+  <div class="caption">Warning</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_sys_wifi_signal_4.png" title="stat_sys_wifi_signal_4" alt="Android asset" />
+  <div class="caption">WiFi</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_notify_wifi_in_range.png" title="stat_notify_wifi_in_range" alt="Android asset" />
+  <div class="caption">WiFi network available</div></td>
+
+</tr>
+<tr>
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_sys_wifi_unavailable.png" title="stat_sys_wifi_unavailable" alt="Android asset" />
+  <div class="caption">WiFi unavailable</div></td>
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_sys_battery_100.png" title="stat_sys_battery_100" alt="Android asset" />
+  <div class="caption">Battery 100%</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_sys_battery_empty.png" title="stat_sys_battery_empty" alt="Android asset" />
+  <div class="caption">Battery empty</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_sys_phone_call.png" title="stat_sys_phone_call" alt="Android asset" />
+  <div class="caption">Call</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_sys_phone_call_forward.png" title="stat_sys_phone_call_forward" alt="Android asset" />
+  <div class="caption">Call forward</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_sys_phone_call_on_hold.png" title="stat_sys_phone_call_on_hold" alt="Android asset" />
+  <div class="caption">Call on hold</div></td>
+
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_sys_gps_on.png" title="stat_sys_gps_on" alt="Android asset" />
+  <div class="caption">GPS on</div></td>
+
+</tr>
+<tr>
+
+<td class="image-caption-i image-list">
+  <img src="{@docRoot}images/icon_design/stat_notify_missed_call.png" title="stat_notify_missed_call" alt="Android asset" />
+  <div class="caption">Missed call</div></td>
+
+</tr>
+</table>
+
+
diff --git a/docs/html/guide/practices/ui_guidelines/index.jd b/docs/html/guide/practices/ui_guidelines/index.jd
index e19d5b4..61e310a 100644
--- a/docs/html/guide/practices/ui_guidelines/index.jd
+++ b/docs/html/guide/practices/ui_guidelines/index.jd
@@ -6,18 +6,27 @@
 
 
 <p>The Android UI team has begun developing guidelines for the interaction and
-design of Android applications. Look here for articles that describe these
-visual guidelines as we release them.</p>
+visual design of Android applications. Look here for articles that describe
+these guidelines as we release them.</p>
 
-    
+ <dl>
+  <dt><a href="{@docRoot}guide/practices/ui_guidelines/icon_design.html">Icon
+Design Guidelines</a> and <a
+href="{@docRoot}shareables/icon_templates-v1.0.zip">Android Icon Templates Pack
+&raquo; </a></dt>
+  <dd>Your applications need a wide variety of icons, from a launcher icon to
+icons in menus, dialogs, tabs, the status bar, and lists. The Icon Guidelines
+describe each kind of icon in detail, with specifications for the size, color,
+shading, and other details for making all your icons fit in the Android system.
+The Icon Templates Pack is an archive of Photoshop and Illustrator templates and
+filters that make it much simpler to create conforming icons.</dd>
+</dl>
  <dl>
   <dt><a href="widget_design.html">Widget Design Guidelines</a> </dt>
-  <dd>Widgets are a new feature introduced in Cupcake. A widget displays
-an application's most important or timely information at a glance, on a user's
-Home screen. These design guidelines describe how to design widgets that fit
-with others on the Home screen. They include links to graphics files and
-templates that will make your designer's life easier.</dd>
-
+  <dd>A widget displays an application's most important or timely information
+at a glance, on a user's Home screen. These design guidelines describe how to
+design widgets that fit with others on the Home screen. They include links to
+graphics files and templates that will make your designer's life easier.</dd>
 </dl>
 
 
diff --git a/docs/html/images/icon_design/dialog_icon.png b/docs/html/images/icon_design/dialog_icon.png
new file mode 100644
index 0000000..9f92422
--- /dev/null
+++ b/docs/html/images/icon_design/dialog_icon.png
Binary files differ
diff --git a/docs/html/images/icon_design/dialog_light.png b/docs/html/images/icon_design/dialog_light.png
new file mode 100644
index 0000000..85056a9
--- /dev/null
+++ b/docs/html/images/icon_design/dialog_light.png
Binary files differ
diff --git a/docs/html/images/icon_design/do_dont.png b/docs/html/images/icon_design/do_dont.png
new file mode 100644
index 0000000..bc6d649
--- /dev/null
+++ b/docs/html/images/icon_design/do_dont.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_launcher_IM.png b/docs/html/images/icon_design/ic_launcher_IM.png
new file mode 100644
index 0000000..afc35a2
--- /dev/null
+++ b/docs/html/images/icon_design/ic_launcher_IM.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_launcher_alarmclock.png b/docs/html/images/icon_design/ic_launcher_alarmclock.png
new file mode 100644
index 0000000..30ff267
--- /dev/null
+++ b/docs/html/images/icon_design/ic_launcher_alarmclock.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_launcher_browser.png b/docs/html/images/icon_design/ic_launcher_browser.png
new file mode 100644
index 0000000..f58b84a
--- /dev/null
+++ b/docs/html/images/icon_design/ic_launcher_browser.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_launcher_calculator.png b/docs/html/images/icon_design/ic_launcher_calculator.png
new file mode 100644
index 0000000..298c267
--- /dev/null
+++ b/docs/html/images/icon_design/ic_launcher_calculator.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_launcher_calendar.png b/docs/html/images/icon_design/ic_launcher_calendar.png
new file mode 100644
index 0000000..9241090
--- /dev/null
+++ b/docs/html/images/icon_design/ic_launcher_calendar.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_launcher_camera.png b/docs/html/images/icon_design/ic_launcher_camera.png
new file mode 100644
index 0000000..c2d7606
--- /dev/null
+++ b/docs/html/images/icon_design/ic_launcher_camera.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_launcher_contacts.png b/docs/html/images/icon_design/ic_launcher_contacts.png
new file mode 100644
index 0000000..826656f
--- /dev/null
+++ b/docs/html/images/icon_design/ic_launcher_contacts.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_launcher_email.png b/docs/html/images/icon_design/ic_launcher_email.png
new file mode 100644
index 0000000..2fb2637
--- /dev/null
+++ b/docs/html/images/icon_design/ic_launcher_email.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_launcher_email_generic.png b/docs/html/images/icon_design/ic_launcher_email_generic.png
new file mode 100644
index 0000000..590ed70
--- /dev/null
+++ b/docs/html/images/icon_design/ic_launcher_email_generic.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_launcher_gallery.png b/docs/html/images/icon_design/ic_launcher_gallery.png
new file mode 100644
index 0000000..965fb71
--- /dev/null
+++ b/docs/html/images/icon_design/ic_launcher_gallery.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_launcher_generic_application.png b/docs/html/images/icon_design/ic_launcher_generic_application.png
new file mode 100644
index 0000000..75024841
--- /dev/null
+++ b/docs/html/images/icon_design/ic_launcher_generic_application.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_launcher_google_talk.png b/docs/html/images/icon_design/ic_launcher_google_talk.png
new file mode 100644
index 0000000..1618eb3
--- /dev/null
+++ b/docs/html/images/icon_design/ic_launcher_google_talk.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_launcher_maps.png b/docs/html/images/icon_design/ic_launcher_maps.png
new file mode 100644
index 0000000..f436b56
--- /dev/null
+++ b/docs/html/images/icon_design/ic_launcher_maps.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_launcher_marketplace.png b/docs/html/images/icon_design/ic_launcher_marketplace.png
new file mode 100644
index 0000000..f1f578d
--- /dev/null
+++ b/docs/html/images/icon_design/ic_launcher_marketplace.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_launcher_musicplayer_2.png b/docs/html/images/icon_design/ic_launcher_musicplayer_2.png
new file mode 100644
index 0000000..0353b91
--- /dev/null
+++ b/docs/html/images/icon_design/ic_launcher_musicplayer_2.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_launcher_phone_dialer.png b/docs/html/images/icon_design/ic_launcher_phone_dialer.png
new file mode 100644
index 0000000..4e613ec
--- /dev/null
+++ b/docs/html/images/icon_design/ic_launcher_phone_dialer.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_launcher_settings.png b/docs/html/images/icon_design/ic_launcher_settings.png
new file mode 100644
index 0000000..16db056
--- /dev/null
+++ b/docs/html/images/icon_design/ic_launcher_settings.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_launcher_sms_mms.png b/docs/html/images/icon_design/ic_launcher_sms_mms.png
new file mode 100644
index 0000000..e2ac784
--- /dev/null
+++ b/docs/html/images/icon_design/ic_launcher_sms_mms.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_launcher_video_camera.png b/docs/html/images/icon_design/ic_launcher_video_camera.png
new file mode 100644
index 0000000..e80255a
--- /dev/null
+++ b/docs/html/images/icon_design/ic_launcher_video_camera.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_launcher_voicedial.png b/docs/html/images/icon_design/ic_launcher_voicedial.png
new file mode 100644
index 0000000..0c84fba
--- /dev/null
+++ b/docs/html/images/icon_design/ic_launcher_voicedial.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_launcher_voicesearch.png b/docs/html/images/icon_design/ic_launcher_voicesearch.png
new file mode 100644
index 0000000..09d5199
--- /dev/null
+++ b/docs/html/images/icon_design/ic_launcher_voicesearch.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_launcher_youtube.png b/docs/html/images/icon_design/ic_launcher_youtube.png
new file mode 100644
index 0000000..48d268d
--- /dev/null
+++ b/docs/html/images/icon_design/ic_launcher_youtube.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_add.png b/docs/html/images/icon_design/ic_menu_add.png
new file mode 100644
index 0000000..6752bfd
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_add.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_archive.png b/docs/html/images/icon_design/ic_menu_archive.png
new file mode 100644
index 0000000..a4599e3
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_archive.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_attachment.png b/docs/html/images/icon_design/ic_menu_attachment.png
new file mode 100644
index 0000000..89d626f
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_attachment.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_back.png b/docs/html/images/icon_design/ic_menu_back.png
new file mode 100644
index 0000000..5ce50eb
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_back.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_call.png b/docs/html/images/icon_design/ic_menu_call.png
new file mode 100644
index 0000000..a63f86b
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_call.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_camera.png b/docs/html/images/icon_design/ic_menu_camera.png
new file mode 100644
index 0000000..cdf7ca3
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_camera.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_camera_video_view.png b/docs/html/images/icon_design/ic_menu_camera_video_view.png
new file mode 100644
index 0000000..f7e52c2
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_camera_video_view.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_close_clear_cancel.png b/docs/html/images/icon_design/ic_menu_close_clear_cancel.png
new file mode 100644
index 0000000..619858c
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_close_clear_cancel.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_compass.png b/docs/html/images/icon_design/ic_menu_compass.png
new file mode 100644
index 0000000..7717dde
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_compass.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_delete.png b/docs/html/images/icon_design/ic_menu_delete.png
new file mode 100644
index 0000000..7d95494
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_delete.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_directions.png b/docs/html/images/icon_design/ic_menu_directions.png
new file mode 100644
index 0000000..67d3ff2
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_directions.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_edit.png b/docs/html/images/icon_design/ic_menu_edit.png
new file mode 100644
index 0000000..41a9c2e
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_edit.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_favorite.png b/docs/html/images/icon_design/ic_menu_favorite.png
new file mode 100644
index 0000000..527d74a
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_favorite.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_forward.png b/docs/html/images/icon_design/ic_menu_forward.png
new file mode 100644
index 0000000..0936fac
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_forward.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_gallery.png b/docs/html/images/icon_design/ic_menu_gallery.png
new file mode 100644
index 0000000..f61bbd8
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_gallery.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_goto.png b/docs/html/images/icon_design/ic_menu_goto.png
new file mode 100644
index 0000000..40183eb
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_goto.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_help.png b/docs/html/images/icon_design/ic_menu_help.png
new file mode 100644
index 0000000..7c55dfd
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_help.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_home.png b/docs/html/images/icon_design/ic_menu_home.png
new file mode 100644
index 0000000..34943f6
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_home.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_info_details.png b/docs/html/images/icon_design/ic_menu_info_details.png
new file mode 100644
index 0000000..1786d1e
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_info_details.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_mapmode.png b/docs/html/images/icon_design/ic_menu_mapmode.png
new file mode 100644
index 0000000..d85cab5
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_mapmode.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_mark.png b/docs/html/images/icon_design/ic_menu_mark.png
new file mode 100644
index 0000000..5e95da7
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_mark.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_more.png b/docs/html/images/icon_design/ic_menu_more.png
new file mode 100644
index 0000000..2091527
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_more.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_mylocation.png b/docs/html/images/icon_design/ic_menu_mylocation.png
new file mode 100644
index 0000000..14b0af8
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_mylocation.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_play_clip.png b/docs/html/images/icon_design/ic_menu_play_clip.png
new file mode 100644
index 0000000..4669947
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_play_clip.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_preferences.png b/docs/html/images/icon_design/ic_menu_preferences.png
new file mode 100644
index 0000000..b8e7141
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_preferences.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_recent_history.png b/docs/html/images/icon_design/ic_menu_recent_history.png
new file mode 100644
index 0000000..4ccae5d
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_recent_history.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_refresh.png b/docs/html/images/icon_design/ic_menu_refresh.png
new file mode 100644
index 0000000..77d70dd
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_refresh.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_rotate.png b/docs/html/images/icon_design/ic_menu_rotate.png
new file mode 100644
index 0000000..27368b2
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_rotate.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_save.png b/docs/html/images/icon_design/ic_menu_save.png
new file mode 100644
index 0000000..36d50b3
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_save.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_search.png b/docs/html/images/icon_design/ic_menu_search.png
new file mode 100644
index 0000000..94446db
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_search.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_send.png b/docs/html/images/icon_design/ic_menu_send.png
new file mode 100644
index 0000000..74c096d
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_send.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_share.png b/docs/html/images/icon_design/ic_menu_share.png
new file mode 100644
index 0000000..44db9b1
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_share.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_shuffle.png b/docs/html/images/icon_design/ic_menu_shuffle.png
new file mode 100644
index 0000000..cb7009d
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_shuffle.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_upload.png b/docs/html/images/icon_design/ic_menu_upload.png
new file mode 100644
index 0000000..1c0dd3f
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_upload.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_view.png b/docs/html/images/icon_design/ic_menu_view.png
new file mode 100644
index 0000000..69828a9
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_view.png
Binary files differ
diff --git a/docs/html/images/icon_design/ic_menu_zoom.png b/docs/html/images/icon_design/ic_menu_zoom.png
new file mode 100644
index 0000000..0b8c4e8
--- /dev/null
+++ b/docs/html/images/icon_design/ic_menu_zoom.png
Binary files differ
diff --git a/docs/html/images/icon_design/icon_guidelines_logo.png b/docs/html/images/icon_design/icon_guidelines_logo.png
new file mode 100644
index 0000000..9362c8f
--- /dev/null
+++ b/docs/html/images/icon_design/icon_guidelines_logo.png
Binary files differ
diff --git a/docs/html/images/icon_design/launcher_light.png b/docs/html/images/icon_design/launcher_light.png
new file mode 100644
index 0000000..8a94e1d
--- /dev/null
+++ b/docs/html/images/icon_design/launcher_light.png
Binary files differ
diff --git a/docs/html/images/icon_design/launcher_palette_black.png b/docs/html/images/icon_design/launcher_palette_black.png
new file mode 100644
index 0000000..fba096f
--- /dev/null
+++ b/docs/html/images/icon_design/launcher_palette_black.png
Binary files differ
diff --git a/docs/html/images/icon_design/launcher_palette_dark.png b/docs/html/images/icon_design/launcher_palette_dark.png
new file mode 100644
index 0000000..3735542
--- /dev/null
+++ b/docs/html/images/icon_design/launcher_palette_dark.png
Binary files differ
diff --git a/docs/html/images/icon_design/launcher_palette_gradient_dark.png b/docs/html/images/icon_design/launcher_palette_gradient_dark.png
new file mode 100644
index 0000000..3735542
--- /dev/null
+++ b/docs/html/images/icon_design/launcher_palette_gradient_dark.png
Binary files differ
diff --git a/docs/html/images/icon_design/launcher_palette_gradient_light.png b/docs/html/images/icon_design/launcher_palette_gradient_light.png
new file mode 100644
index 0000000..f1121eb
--- /dev/null
+++ b/docs/html/images/icon_design/launcher_palette_gradient_light.png
Binary files differ
diff --git a/docs/html/images/icon_design/launcher_palette_gradient_medium.png b/docs/html/images/icon_design/launcher_palette_gradient_medium.png
new file mode 100644
index 0000000..1442b17
--- /dev/null
+++ b/docs/html/images/icon_design/launcher_palette_gradient_medium.png
Binary files differ
diff --git a/docs/html/images/icon_design/launcher_palette_light.png b/docs/html/images/icon_design/launcher_palette_light.png
new file mode 100644
index 0000000..f1121eb
--- /dev/null
+++ b/docs/html/images/icon_design/launcher_palette_light.png
Binary files differ
diff --git a/docs/html/images/icon_design/launcher_palette_medium.png b/docs/html/images/icon_design/launcher_palette_medium.png
new file mode 100644
index 0000000..1442b17
--- /dev/null
+++ b/docs/html/images/icon_design/launcher_palette_medium.png
Binary files differ
diff --git a/docs/html/images/icon_design/launcher_palette_white.png b/docs/html/images/icon_design/launcher_palette_white.png
new file mode 100644
index 0000000..8d7ac41
--- /dev/null
+++ b/docs/html/images/icon_design/launcher_palette_white.png
Binary files differ
diff --git a/docs/html/images/icon_design/launcher_structure.png b/docs/html/images/icon_design/launcher_structure.png
new file mode 100644
index 0000000..53e4d9a
--- /dev/null
+++ b/docs/html/images/icon_design/launcher_structure.png
Binary files differ
diff --git a/docs/html/images/icon_design/listview_icon.png b/docs/html/images/icon_design/listview_icon.png
new file mode 100644
index 0000000..5711d88
--- /dev/null
+++ b/docs/html/images/icon_design/listview_icon.png
Binary files differ
diff --git a/docs/html/images/icon_design/listview_icon_details.png b/docs/html/images/icon_design/listview_icon_details.png
new file mode 100644
index 0000000..5a68416
--- /dev/null
+++ b/docs/html/images/icon_design/listview_icon_details.png
Binary files differ
diff --git a/docs/html/images/icon_design/menu_light.png b/docs/html/images/icon_design/menu_light.png
new file mode 100644
index 0000000..93ed38b
--- /dev/null
+++ b/docs/html/images/icon_design/menu_light.png
Binary files differ
diff --git a/docs/html/images/icon_design/menu_palette_black.png b/docs/html/images/icon_design/menu_palette_black.png
new file mode 100644
index 0000000..fba096f
--- /dev/null
+++ b/docs/html/images/icon_design/menu_palette_black.png
Binary files differ
diff --git a/docs/html/images/icon_design/menu_palette_fill.png b/docs/html/images/icon_design/menu_palette_fill.png
new file mode 100644
index 0000000..7079bda
--- /dev/null
+++ b/docs/html/images/icon_design/menu_palette_fill.png
Binary files differ
diff --git a/docs/html/images/icon_design/menu_palette_gradient_medium.png b/docs/html/images/icon_design/menu_palette_gradient_medium.png
new file mode 100644
index 0000000..a806adb
--- /dev/null
+++ b/docs/html/images/icon_design/menu_palette_gradient_medium.png
Binary files differ
diff --git a/docs/html/images/icon_design/menu_palette_white.png b/docs/html/images/icon_design/menu_palette_white.png
new file mode 100644
index 0000000..8d7ac41
--- /dev/null
+++ b/docs/html/images/icon_design/menu_palette_white.png
Binary files differ
diff --git a/docs/html/images/icon_design/menu_structure.png b/docs/html/images/icon_design/menu_structure.png
new file mode 100644
index 0000000..ab14015
--- /dev/null
+++ b/docs/html/images/icon_design/menu_structure.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_notify_alarm.png b/docs/html/images/icon_design/stat_notify_alarm.png
new file mode 100644
index 0000000..1b01b85
--- /dev/null
+++ b/docs/html/images/icon_design/stat_notify_alarm.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_notify_calendar.png b/docs/html/images/icon_design/stat_notify_calendar.png
new file mode 100644
index 0000000..4433a16
--- /dev/null
+++ b/docs/html/images/icon_design/stat_notify_calendar.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_notify_chat.png b/docs/html/images/icon_design/stat_notify_chat.png
new file mode 100644
index 0000000..238f043
--- /dev/null
+++ b/docs/html/images/icon_design/stat_notify_chat.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_notify_disk_full.png b/docs/html/images/icon_design/stat_notify_disk_full.png
new file mode 100644
index 0000000..9120f00
--- /dev/null
+++ b/docs/html/images/icon_design/stat_notify_disk_full.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_notify_email.png b/docs/html/images/icon_design/stat_notify_email.png
new file mode 100644
index 0000000..d84a247
--- /dev/null
+++ b/docs/html/images/icon_design/stat_notify_email.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_notify_email_generic.png b/docs/html/images/icon_design/stat_notify_email_generic.png
new file mode 100644
index 0000000..686033f
--- /dev/null
+++ b/docs/html/images/icon_design/stat_notify_email_generic.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_notify_missed_call.png b/docs/html/images/icon_design/stat_notify_missed_call.png
new file mode 100644
index 0000000..fe746b3
--- /dev/null
+++ b/docs/html/images/icon_design/stat_notify_missed_call.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_notify_musicplayer.png b/docs/html/images/icon_design/stat_notify_musicplayer.png
new file mode 100644
index 0000000..fd92c18
--- /dev/null
+++ b/docs/html/images/icon_design/stat_notify_musicplayer.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_notify_sms.png b/docs/html/images/icon_design/stat_notify_sms.png
new file mode 100644
index 0000000..b437d5b
--- /dev/null
+++ b/docs/html/images/icon_design/stat_notify_sms.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_notify_sync_anim0.png b/docs/html/images/icon_design/stat_notify_sync_anim0.png
new file mode 100644
index 0000000..0edf692
--- /dev/null
+++ b/docs/html/images/icon_design/stat_notify_sync_anim0.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_notify_sync_error.png b/docs/html/images/icon_design/stat_notify_sync_error.png
new file mode 100644
index 0000000..3078b8c
--- /dev/null
+++ b/docs/html/images/icon_design/stat_notify_sync_error.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_notify_voicemail.png b/docs/html/images/icon_design/stat_notify_voicemail.png
new file mode 100644
index 0000000..658fa05
--- /dev/null
+++ b/docs/html/images/icon_design/stat_notify_voicemail.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_notify_wifi_in_range.png b/docs/html/images/icon_design/stat_notify_wifi_in_range.png
new file mode 100644
index 0000000..e9c74b4
--- /dev/null
+++ b/docs/html/images/icon_design/stat_notify_wifi_in_range.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_sys_battery_100.png b/docs/html/images/icon_design/stat_sys_battery_100.png
new file mode 100644
index 0000000..d280aeb
--- /dev/null
+++ b/docs/html/images/icon_design/stat_sys_battery_100.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_sys_battery_empty.png b/docs/html/images/icon_design/stat_sys_battery_empty.png
new file mode 100644
index 0000000..4a5e99e
--- /dev/null
+++ b/docs/html/images/icon_design/stat_sys_battery_empty.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_sys_data_bluetooth.png b/docs/html/images/icon_design/stat_sys_data_bluetooth.png
new file mode 100644
index 0000000..7a8b78f
--- /dev/null
+++ b/docs/html/images/icon_design/stat_sys_data_bluetooth.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_sys_data_bluetooth_connected.png b/docs/html/images/icon_design/stat_sys_data_bluetooth_connected.png
new file mode 100644
index 0000000..f09b83b
--- /dev/null
+++ b/docs/html/images/icon_design/stat_sys_data_bluetooth_connected.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_sys_data_connected_3g.png b/docs/html/images/icon_design/stat_sys_data_connected_3g.png
new file mode 100644
index 0000000..a109280
--- /dev/null
+++ b/docs/html/images/icon_design/stat_sys_data_connected_3g.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_sys_data_connected_e.png b/docs/html/images/icon_design/stat_sys_data_connected_e.png
new file mode 100644
index 0000000..c552644
--- /dev/null
+++ b/docs/html/images/icon_design/stat_sys_data_connected_e.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_sys_data_connected_g.png b/docs/html/images/icon_design/stat_sys_data_connected_g.png
new file mode 100644
index 0000000..f7edb49
--- /dev/null
+++ b/docs/html/images/icon_design/stat_sys_data_connected_g.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_sys_data_usb.png b/docs/html/images/icon_design/stat_sys_data_usb.png
new file mode 100644
index 0000000..2d0da4c
--- /dev/null
+++ b/docs/html/images/icon_design/stat_sys_data_usb.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_sys_gps_on.png b/docs/html/images/icon_design/stat_sys_gps_on.png
new file mode 100644
index 0000000..a2c677d
--- /dev/null
+++ b/docs/html/images/icon_design/stat_sys_gps_on.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_sys_install_complete.png b/docs/html/images/icon_design/stat_sys_install_complete.png
new file mode 100644
index 0000000..62dba5b
--- /dev/null
+++ b/docs/html/images/icon_design/stat_sys_install_complete.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_sys_phone_call.png b/docs/html/images/icon_design/stat_sys_phone_call.png
new file mode 100644
index 0000000..ad53693
--- /dev/null
+++ b/docs/html/images/icon_design/stat_sys_phone_call.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_sys_phone_call_forward.png b/docs/html/images/icon_design/stat_sys_phone_call_forward.png
new file mode 100644
index 0000000..ed4b6ec
--- /dev/null
+++ b/docs/html/images/icon_design/stat_sys_phone_call_forward.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_sys_phone_call_on_hold.png b/docs/html/images/icon_design/stat_sys_phone_call_on_hold.png
new file mode 100644
index 0000000..9216447
--- /dev/null
+++ b/docs/html/images/icon_design/stat_sys_phone_call_on_hold.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_sys_r_signal_4.png b/docs/html/images/icon_design/stat_sys_r_signal_4.png
new file mode 100644
index 0000000..f04fb11
--- /dev/null
+++ b/docs/html/images/icon_design/stat_sys_r_signal_4.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_sys_ringer_silent_old.png b/docs/html/images/icon_design/stat_sys_ringer_silent_old.png
new file mode 100644
index 0000000..d125ce5
--- /dev/null
+++ b/docs/html/images/icon_design/stat_sys_ringer_silent_old.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_sys_ringer_vibrate.png b/docs/html/images/icon_design/stat_sys_ringer_vibrate.png
new file mode 100644
index 0000000..665ca38
--- /dev/null
+++ b/docs/html/images/icon_design/stat_sys_ringer_vibrate.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_sys_signal_4.png b/docs/html/images/icon_design/stat_sys_signal_4.png
new file mode 100644
index 0000000..a3320cb
--- /dev/null
+++ b/docs/html/images/icon_design/stat_sys_signal_4.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_sys_signal_flightmode.png b/docs/html/images/icon_design/stat_sys_signal_flightmode.png
new file mode 100644
index 0000000..516ec2f
--- /dev/null
+++ b/docs/html/images/icon_design/stat_sys_signal_flightmode.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_sys_signal_null.png b/docs/html/images/icon_design/stat_sys_signal_null.png
new file mode 100644
index 0000000..5aa23f6
--- /dev/null
+++ b/docs/html/images/icon_design/stat_sys_signal_null.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_sys_speakerphone.png b/docs/html/images/icon_design/stat_sys_speakerphone.png
new file mode 100644
index 0000000..642dfd4
--- /dev/null
+++ b/docs/html/images/icon_design/stat_sys_speakerphone.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_sys_warning.png b/docs/html/images/icon_design/stat_sys_warning.png
new file mode 100644
index 0000000..be00f47
--- /dev/null
+++ b/docs/html/images/icon_design/stat_sys_warning.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_sys_wifi_signal_4.png b/docs/html/images/icon_design/stat_sys_wifi_signal_4.png
new file mode 100644
index 0000000..2062aad
--- /dev/null
+++ b/docs/html/images/icon_design/stat_sys_wifi_signal_4.png
Binary files differ
diff --git a/docs/html/images/icon_design/stat_sys_wifi_unavailable.png b/docs/html/images/icon_design/stat_sys_wifi_unavailable.png
new file mode 100644
index 0000000..53dd45b
--- /dev/null
+++ b/docs/html/images/icon_design/stat_sys_wifi_unavailable.png
Binary files differ
diff --git a/docs/html/images/icon_design/statusbar_light.png b/docs/html/images/icon_design/statusbar_light.png
new file mode 100644
index 0000000..ddebc2d
--- /dev/null
+++ b/docs/html/images/icon_design/statusbar_light.png
Binary files differ
diff --git a/docs/html/images/icon_design/statusbar_palette_black.png b/docs/html/images/icon_design/statusbar_palette_black.png
new file mode 100644
index 0000000..fba096f
--- /dev/null
+++ b/docs/html/images/icon_design/statusbar_palette_black.png
Binary files differ
diff --git a/docs/html/images/icon_design/statusbar_palette_fill.png b/docs/html/images/icon_design/statusbar_palette_fill.png
new file mode 100644
index 0000000..bbf652c
--- /dev/null
+++ b/docs/html/images/icon_design/statusbar_palette_fill.png
Binary files differ
diff --git a/docs/html/images/icon_design/statusbar_palette_grey.png b/docs/html/images/icon_design/statusbar_palette_grey.png
new file mode 100644
index 0000000..0abb7f4
--- /dev/null
+++ b/docs/html/images/icon_design/statusbar_palette_grey.png
Binary files differ
diff --git a/docs/html/images/icon_design/statusbar_palette_white.png b/docs/html/images/icon_design/statusbar_palette_white.png
new file mode 100644
index 0000000..8d7ac41
--- /dev/null
+++ b/docs/html/images/icon_design/statusbar_palette_white.png
Binary files differ
diff --git a/docs/html/images/icon_design/statusbar_structure.png b/docs/html/images/icon_design/statusbar_structure.png
new file mode 100644
index 0000000..e7243ee
--- /dev/null
+++ b/docs/html/images/icon_design/statusbar_structure.png
Binary files differ
diff --git a/docs/html/images/icon_design/tab_icon_selected.png b/docs/html/images/icon_design/tab_icon_selected.png
new file mode 100644
index 0000000..66a8475
--- /dev/null
+++ b/docs/html/images/icon_design/tab_icon_selected.png
Binary files differ
diff --git a/docs/html/images/icon_design/tab_icon_unselected.png b/docs/html/images/icon_design/tab_icon_unselected.png
new file mode 100644
index 0000000..80ae9c1
--- /dev/null
+++ b/docs/html/images/icon_design/tab_icon_unselected.png
Binary files differ
diff --git a/docs/html/images/icon_design/tab_palette_selected_fill.png b/docs/html/images/icon_design/tab_palette_selected_fill.png
new file mode 100644
index 0000000..7079bda
--- /dev/null
+++ b/docs/html/images/icon_design/tab_palette_selected_fill.png
Binary files differ
diff --git a/docs/html/images/icon_design/tab_selected_light.png b/docs/html/images/icon_design/tab_selected_light.png
new file mode 100644
index 0000000..3a87c5b
--- /dev/null
+++ b/docs/html/images/icon_design/tab_selected_light.png
Binary files differ
diff --git a/docs/html/images/icon_design/tab_unselected_light.png b/docs/html/images/icon_design/tab_unselected_light.png
new file mode 100644
index 0000000..f888161
--- /dev/null
+++ b/docs/html/images/icon_design/tab_unselected_light.png
Binary files differ
diff --git a/docs/html/index.jd b/docs/html/index.jd
index 883170a3..ea326b0 100644
--- a/docs/html/index.jd
+++ b/docs/html/index.jd
@@ -116,10 +116,10 @@
     'sdk': {
       'layout':"imgLeft",
       'icon':"sdk-small.png",
-      'name':"SDK 1.5 r1",
+      'name':"SDK 1.5 r2",
       'img':"sdk-large.png",
-      'title':"Android 1.5 SDK r1",
-      'desc': "<p>The final version of the Android 1.5 SDK is now available. It includes new APIs for Android 1.5, updated developer tools, multiple platform versions, and a Google APIs add-on.</p><p><a href='{@docRoot}sdk/1.5_r1/index.html'>Download Android 1.5 SDK</a></p>"
+      'title':"Android 1.5 SDK",
+      'desc': "<p>Android 1.5 SDK is now available. It includes new APIs for Android 1.5, updated developer tools, multiple platform versions, and a Google APIs add-on.</p><p><a href='{@docRoot}sdk/1.5_r2/index.html'>Download Android 1.5 SDK</a></p>"
     },
 
     'mapskey': {
diff --git a/docs/html/robots.txt b/docs/html/robots.txt
index 085b79d..7046373 100644
--- a/docs/html/robots.txt
+++ b/docs/html/robots.txt
@@ -1,7 +1,8 @@
-User-Agent: *

-Allow: /

-Disallow: /gae_shell/

-Disallow: /assets/

-Disallow: /images/

-Disallow: /sdk/preview/

-Sitemap: http://developer.android.com/sitemap.txt

+User-Agent: *
+Allow: /
+Disallow: /gae_shell/
+Disallow: /assets/
+Disallow: /images/
+Disallow: /sdk/preview/
+Disallow: /shareables/
+Sitemap: http://developer.android.com/sitemap.txt
diff --git a/docs/html/sdk/1.5_r2/index.jd b/docs/html/sdk/1.5_r2/index.jd
new file mode 100644
index 0000000..15342a4
--- /dev/null
+++ b/docs/html/sdk/1.5_r2/index.jd
@@ -0,0 +1,87 @@
+sdk.version=1.5
+sdk.rel.id=2
+sdk.date=May 2009
+
+sdk.win_download=android-sdk-windows-1.5_r2.zip
+sdk.win_bytes=178346828
+sdk.win_checksum=ba54ac6bda45921d442b74b6de6ff6a9
+
+sdk.mac_download=android-sdk-mac_x86-1.5_r2.zip
+sdk.mac_bytes=169945128
+sdk.mac_checksum=f4e06a5194410243f213d0177713d6c9
+
+sdk.linux_download=android-sdk-linux_x86-1.5_r2.zip
+sdk.linux_bytes=165035130
+sdk.linux_checksum=1d3c3d099e95a31c43a7b3e6ae307ed3
+
+page.title=Android 1.5 SDK, Release 2
+@jd:body
+
+<p>For more information on this SDK release, read the
+<a href="{@docRoot}sdk/RELEASENOTES.html#1.5_r2">Release Notes</a>.</p>
+
+<h2>SDK Contents</h2>
+
+<h4>Development tools</h4>
+
+<p>The SDK includes a full set of tools for developing and debugging application code and designing an application UI. You can read about the tools in the  
+<a href="{@docRoot}guide/developing/tools/index.html">Dev Guide</a> and access them in the <code>&lt;sdk&gt;/tools/</code> directory. 
+
+<p>The tools package in this SDK includes updates from those provided in the previous SDK. The tools also require a different project structure. To use the new tools, you need to migrate your applications to the new development environment. For more information about how to migrate, see <a href="{@docRoot}sdk/1.5_r2/upgrading.html">Upgrading the SDK</a>.
+
+<p>For more information about the new tools features, see the <a href="{@docRoot}sdk/RELEASENOTES.html">SDK Release Notes</a>. 
+
+<h4 id="system_images">Android Platforms</h4>
+
+<p>This SDK includes multiple Android platform versions that you use to develop applications. For each version, both a fully compliant Android library and system image are provided. The table below lists the platform versions included in this SDK. For more information about a platform version &mdash; features, applications included, localizations, API changes, and so on &mdash; see its Version Notes. </p>
+
+<table style="margin-right:1em;" width="80%">
+<tr>
+<th><nobr>Platform</nobr></th><th><nobr>API Level</nobr></th><th>Notes</th><th>Description</th>
+</tr>
+
+<tr>
+<td width="5%"><nobr>Android 1.5</nobr></td>
+<td  width="5%">3</td>
+<td  width="5%"><nobr><a href="{@docRoot}sdk/android-1.5.html">Version Notes</a></nobr></td>
+<td>Includes a standard Android 1.5 library and system image with a set of development applications. Does not include any external libraries (such as the Maps external library).</td>
+</tr>
+<tr>
+<td width="5%"><nobr>Android 1.1</nobr></td>
+<td  width="5%">2</td>
+<td  width="5%"><nobr><a href="{@docRoot}sdk/android-1.1.html">Version Notes</a></nobr></td>
+<td>Includes a compliant Android 1.1 library and system image with a set of development applications. Also includes the Maps external library (due to legacy build system issues).</td>
+</tr>
+</table>
+
+<h4 id="system_images">SDK Add-Ons</h4>
+
+<p>An SDK add-on provides a development environment for an Android external library or a customized (but fully compliant) Android system image. This SDK includes the SDK add-on listed below. The Android system API Level required by the add-on is noted.</p>
+
+<table style="margin-right:1em;" width="80%">
+<tr>
+<th><nobr>Add-On</nobr></th><th><nobr>API Level</nobr></th><th>Notes</th><th>Description</th>
+</tr>
+<tr>
+<td width="5%"><nobr>Google APIs</nobr></td>
+<td  width="5%">3</td>
+<td  width="5%">&nbsp;</td>
+<td>Includes the com.google.android.maps external library, a compliant 
+system image, a {@link android.location.Geocoder Geocoder}
+backend service implementation, documentation, and sample code. </td>
+</tr>
+</table>
+
+<h4>Sample Code and Applications</h4>
+
+<p>You can look at a variety of tutorials and samples in the <a href="{@docRoot}guide/samples/index.html">Dev Guide</a> and access the sample code itself
+in the <code>&lt;sdk&gt;/platforms/android-1.5/samples/</code> directory of the SDK package. Note the new location &mdash; the SDK now includes multiple platform versions that you can develop against and each has its own sample code directory. </p>
+
+<h4>Documentation</h4>
+
+<p>The SDK package includes a full set of local documentation. To view it, open the <code>&lt;sdk&gt;/documentation.html</code> file in a web browser. If you are developing in an IDE such as Eclipse, you can also view the reference documentation directly in the IDE. </p>
+
+<p>The most current documentation is always available on the Android Developers site:</p>
+
+<p style="margin-left:2em;"><a href="http://developer.android.com/index.html">http://developer.android.com/</a></p>
+
diff --git a/docs/html/sdk/1.5_r2/installing.jd b/docs/html/sdk/1.5_r2/installing.jd
new file mode 100644
index 0000000..69b2c1b
--- /dev/null
+++ b/docs/html/sdk/1.5_r2/installing.jd
@@ -0,0 +1,332 @@
+sdk.version=1.5
+sdk.rel.id=2
+sdk.date=April 2009
+
+page.title=Installing the Android SDK
+@jd:body
+
+
+<p>This page describes how to install the Android SDK and set up your
+development environment. If you haven't downloaded the SDK, you can
+do so from the 
+<a href="{@docRoot}sdk/1.5_r2/index.html">Download</a> page. Once you've downloaded
+the SDK, return here.</p>
+
+<p>If you encounter any problems during installation, see the 
+<a href="#installnotes">Installation Notes</a> at the bottom of
+this page.</p>
+
+<h4 style="margin-top">Upgrading?</h4>
+<p>If you have already developed applications using an earlier version
+of the SDK, please read 
+<a href="{@docRoot}sdk/1.5_r2/upgrading.html"><strong>Upgrading the
+SDK</strong></a></b>, instead.
+</p>
+
+
+<h2 id="setup">Preparing for Installation</h2>
+
+<p>Before you begin, take a moment to confirm that your development machine meets the 
+<a href="{@docRoot}sdk/1.5_r2/requirements.html">System Requirements</a>.
+</p>
+
+<p>If you will be developing on Eclipse with the Android Development
+Tools (ADT) Plugin &mdash; the recommended path if you are new to
+Android &mdash; make sure that you have a suitable version of Eclipse
+installed on your computer (3.3 or newer). If you need to install Eclipse, you can
+download it from this location: </p>
+
+<p style="margin-left:2em;"><a href=
+"http://www.eclipse.org/downloads/">http://www.eclipse.org/downloads/</a
+></p>
+
+<p>A Java or RCP version of Eclipse is recommended. </p>
+
+<h2 id="installingsdk">Installing the SDK</h2>
+
+<p>After downloading the SDK, unpack the .zip archive to a suitable location on your machine. 
+By default, the SDK files are unpacked into a directory named 
+<code>android_sdk_<em>&lt;platform</em>&gt;_<em>&lt;release&gt;</em></code>. 
+The directory contains a local copy of the documentation (accessible by opening
+<code>documentation.html</code> in your browser) and the subdirectories 
+<code>tools/</code>, <code>add-ons/</code>, <code>platforms/</code>, and others. Inside
+each subdirectory of <code>platforms/</code> you'll find <code>samples/</code>, which includes
+code samples that are specific to each version of the platform.</p>
+
+<p>Make a note of the name and location of the unpacked SDK directory on your system &mdash; you 
+will need to refer to the SDK directory later, when setting up the Android plugin or when 
+using the SDK tools.</p>
+
+<p>Optionally, you may want to add the location of the SDK's primary <code>tools</code> directory 
+to your system PATH. The primary <code>tools/</code> directory is located at the root of the 
+SDK folder. Adding <code>tools</code> to your path lets you run Android Debug Bridge (adb) and 
+the other command line <a href="{@docRoot}guide/developing/tools/index.html">tools</a> without 
+needing to supply the full path to the tools directory. </p>
+<ul>
+    <li>On Linux, edit your <code>~/.bash_profile</code> or <code>~/.bashrc</code> file. Look
+    for a line that sets the PATH environment variable and add the
+    full path to the <code>tools/</code> directory to it. If you don't 
+    see a line setting the path, you can add one:</li>
+
+    <ul><code>export PATH=${PATH}:<em>&lt;your_sdk_dir&gt;</em>/tools</code></ul>
+
+    <li>On a Mac, look in your home directory for <code>.bash_profile</code> and
+    proceed as for Linux. You can create the <code>.bash_profile</code> if 
+    you haven't already set one up on your machine. </li>
+
+    <li>On Windows, right-click on My Computer, and select Properties.  
+  Under the Advanced tab, hit the Environment Variables button, and in the
+  dialog that comes up, double-click on Path (under System Variables). Add the full path to the 
+  <code>tools/</code> directory to the path. </li>
+  </ul>
+
+<p>Note that, if you update your SDK in the future, you 
+should remember to update your PATH settings to point to the new location, if different.</p>
+
+<p>If you will be using the Eclipse IDE as your development environment,
+the next section describes how to install the Android Development Tools plugin and set up Eclipse. 
+If you choose not to use Eclipse, you can 
+develop Android applications in an IDE of your choice and then compile, debug and deploy using
+the tools included in the SDK (skip to <a href="#next">Next Steps</a>).</p>
+
+
+<h2 id="installingplugin">Installing the ADT Plugin for Eclipse</h2>
+
+<p>Android offers a custom plugin for the Eclipse IDE, called Android
+Development Tools (ADT), that is designed to give you a powerful,
+integrated environment in which to build Android applications. It
+extends the capabilites of Eclipse to let you quickly set up new Android
+projects, create an application UI, add components based on the Android
+Framework API, debug your applications using the Android SDK tools, and even export
+signed (or unsigned) APKs in order to distribute your application.</p>
+
+<p>In general, using Eclipse with ADT is a highly recommended
+approach to Android development and is the fastest way to get started.
+(If you prefer to work in an IDE other than Eclipse,
+you do not need to install Eclipse or ADT, instead, you can directly
+use the SDK tools to build and debug your application.)</p>
+
+<p>Once you have Eclipse installed, as described in <a href="#setup">Preparing for 
+Installation</a>, follow the steps below to
+download the ADT plugin and install it in your respective Eclipse
+environment. </p>
+
+<table style="font-size:100%">
+<tr><th>Eclipse 3.3 (Europa)</th><th>Eclipse 3.4 (Ganymede)</th></tr>
+<tr>
+<td width="45%">
+<!-- 3.3 steps -->
+<ol>
+    <li>Start Eclipse, then select <strong>Help</strong> &gt; <strong>Software Updates</strong> 
+&gt; <strong>Find and Install...</strong>. </li>
+    <li>In the dialog that appears, select <strong>Search for new features to install</strong> 
+and click <strong>Next</strong>. </li>
+    <li>Click <strong>New Remote Site</strong>. </li>
+    <li>In the resulting dialog box, enter a name for the remote site (e.g. "Android Plugin") and 
+    enter the URL:
+        <pre>https://dl-ssl.google.com/android/eclipse/</pre>
+        <p>If you have trouble aqcuiring the plugin, try using "http" in the URL,
+        instead of "https" (https is preferred for security reasons).</p>
+        <p>Click <strong>OK</strong>.</p> </li>
+    <li>You should now see the new site added to the search list (and checked).
+        Click <strong>Finish</strong>. </li>
+    <li>In the subsequent Search Results dialog box, select the checkbox for the
+    "Android Plugin".
+    This will select the nested tools: "Android DDMS" and "Android Development Tools". 
+    Click <strong>Next</strong>.</li>
+    <li>Read and accept the license agreement, then click <strong>Next</strong>. </li>
+    <li>On the following Installation window, click <strong>Finish</strong>. </li>
+    <li>The ADT plugin is not digitally signed. Accept the installation anyway
+        by clicking <strong>Install All</strong>. </li>
+    <li>Restart Eclipse. </li>
+</ol>
+
+</td>
+<td>
+
+<!-- 3.4 steps -->
+<ol>
+    <li>Start Eclipse, then select <strong>Help</strong> &gt; <strong>Software Updates...</strong>.</li>
+    <li>In the dialog that appears, click the <strong>Available Software</strong> tab. </li>
+    <li>Click <strong>Add Site...</strong> </li>
+    <li>Enter the Location:
+      <pre>https://dl-ssl.google.com/android/eclipse/</pre>
+        <p>If you have trouble aqcuiring the plugin, try using "http" in the Location URL,
+        instead of "https" (https is preferred for security reasons).</p>   
+      <p>Click <strong>OK</strong>.</p></li>
+    <li>Back in the Available Software view, you should see the plugin listed by the URL,
+    with "Developer Tools" nested within it. Select the checkbox next to 
+      Developer Tools and click <strong>Install...</strong></li>
+    <li>On the subsequent Install window, "Android DDMS" and "Android Development Tools"
+    should both be checked. Click <strong>Next</strong>. </li>
+    <li>Read and accept the license agreement, then click <strong>Finish</strong>.</li>
+    <li>Restart Eclipse. </li>
+</ol>
+
+</td>
+</tr>
+</table>
+
+<p>Now modify your Eclipse preferences to point to the Android SDK directory:</p>
+<ol>
+    <li>Select <strong>Window</strong> &gt; <strong>Preferences...</strong> to open the Preferences
+        panel (Mac: <strong>Eclipse</strong> &gt; <strong>Preferences</strong>).</li>
+    <li>Select <strong>Android</strong> from the left panel. </li>
+    <li>For the <em>SDK Location</em> in the main panel, click <strong>Browse...</strong> and 
+locate your downloaded SDK directory. </li>
+    <li>Click <strong>Apply</strong>, then <strong>OK</strong>.</li>
+</ol>
+
+<p>Done! If you haven't encountered any problems, then you're ready to
+begin developing Android applications. See the 
+<a href="#next">Next Steps</a> section for suggestions on how to start. </p>
+
+
+<h3 id="troubleshooting">Troubleshooting ADT Installation</h3>
+<p> 
+If you are having trouble downloading the ADT plugin after following the steps above, here are 
+some suggestions: </p>
+
+<ul>
+  <li>If Eclipse can not find the remote update site containing the ADT plugin, try changing 
+  the remote site URL to use http, rather than https. That is, set the Location for the remote site to:
+  <pre>http://dl-ssl.google.com/android/eclipse/</pre></li>
+  <li>If you are behind a firewall (such as a corporate firewall), make
+  sure that you have properly configured your proxy settings in Eclipse.
+  In Eclipse 3.3/3.4, you can configure proxy information from the main
+  Eclipse menu in <strong>Window</strong> (on Mac, <strong>Eclipse</strong>) &gt; 
+  <strong>Preferences</strong> &gt; <strong>General</strong> &gt; 
+  <strong>Network Connections</strong>.</li>
+</ul>
+<p> 
+If you are still unable to use Eclipse to download the ADT plugin as a remote update site, you 
+can download the ADT zip file to your local machine and manually install the it:
+</p>
+<ol>
+  <li><a href="{@docRoot}sdk/adt_download.html">Download the ADT zip file</a> (do not unpack it).</li>
+  <li>Follow steps 1 and 2 in the default install instructions (above).</li>
+  <li>In Eclipse 3.3, click <strong>New Archive Site...</strong>. <br/>
+      In Eclipse 3.4, click <strong>Add Site...</strong>, then <strong>Archive...</strong></li>
+  <li>Browse and select the downloaded zip file.</li>
+  <li>Follow the remaining procedures, above, starting from steps 5.</li>
+</ol>
+<p>To update your plugin once you've installed using the zip file, you will have to 
+follow these steps again instead of the default update instructions.</p>
+
+<h4>Other install errors</h4>
+
+<p>Note that there are features of ADT that require some optional 
+Eclipse components (for example, WST). If you encounter an error when 
+installing ADT, your Eclipse installion might not include these components. 
+For information about how to quickly add the necessary components to your 
+Eclipse installation, see the troubleshooting topic 
+<a href="{@docRoot}guide/appendix/faq/troubleshooting.html#installeclipsecomponents">ADT 
+Installation Error: "requires plug-in org.eclipse.wst.sse.ui"</a>.</p>
+
+<h4>For Linux users</h4>
+<p>If you encounter this error when installing the ADT Plugin for Eclipse: 
+<pre>
+An error occurred during provisioning.
+Cannot connect to keystore.
+JKS</pre>
+<p>
+...then your development machine lacks a suitable Java VM. Installing Sun
+Java 6 will resolve this issue and you can then reinstall the ADT
+Plugin.</p>
+
+
+<h2 id="next">Next Steps</h2>
+<p>Once you have completed installation, you are ready to
+begin developing applications. Here are a few ways you can get started: </p>
+
+<p><strong>Learn about Android</strong></p>
+<ul>
+  <li>Take a look at the <a href="{@docRoot}guide/index.html">Dev
+  Guide</a> and the types of information it provides</li>
+  <li>Read an introduction to Android as a platform in <a
+  href="{@docRoot}guide/basics/what-is-android.html">What is
+  Android?</a></li>
+  <li>Learn about the Android framework and how applications run on it in
+  <a href="{@docRoot}guide/topics/fundamentals.html">Application
+  Fundamentals</a></li>
+  <li>Take a look at the Android framework API specification in the <a
+  href="{@docRoot}reference/packages.html">Reference</a> tab</li>
+</ul>
+
+<p><strong>Explore the SDK</strong></p>
+<ul>
+  <li>Get an overview of the <a
+  href="{@docRoot}guide/developing/tools/index.html">development
+  tools</a> that are available to you</li>
+  <li>Read how to develop <a
+  href="{@docRoot}guide/developing/eclipse-adt.html">in Eclipse/ADT</a> or
+  <a href="{@docRoot}guide/developing/other-ide.html">in other IDEs</a>
+  </li>
+</ul>
+
+<p><strong>Explore some code</strong></p>
+<ul>
+  <li>Set up a <a href="{@docRoot}guide/tutorials/hello-world.html">Hello
+  World application</a> (highly recommended, especially for Eclipse users)</li>
+  <li>Follow the <a href="{@docRoot}guide/tutorials/notepad/index.html">
+  Notepad Tutorial</a> to build a full Android application </li>
+  <li>Create a new project for one of the other sample applications
+  included in <code><em>&lt;sdk&gt;</em>/platforms/<em>&lt;platfrom&gt;</em>/samples</code>, 
+  then compile and run it in your development environment</li>
+</ul>
+
+<p><strong>Visit the Android developer groups</strong></p>
+<ul>
+  <li>Take a look at the <a
+  href="{@docRoot}community/index.html">Community</a> tab to see a list of
+  Android developers groups. In particular, you might want to look at the
+  <a href="http://groups.google.com/group/android-developers">Android
+  Developers</a> group to get a sense for what the Android developer
+  community is like.</li>
+</ul>
+
+
+<h2 id="installnotes">Installation Notes</h2>
+
+<h3>Ubuntu Linux Notes</h3>
+
+<ul>
+  <li>If you need help installing and configuring Java on your
+    development machine, you might find these resources helpful: 
+    <ul>
+      <li><a href="https://help.ubuntu.com/community/Java">https://help.ubuntu.com/community/Java </a></li>
+      <li><a href="https://help.ubuntu.com/community/Java">https://help.ubuntu.com/community/JavaInstallation</a></li>
+    </ul>
+  </li>
+  <li>Here are the steps to install Java and Eclipse, prior to installing
+  the Android SDK and ADT Plugin.
+    <ol>
+      <li>If you are running a 64-bit distribution on your development
+      machine, you need to install the <code>ia32-libs</code> package using
+      <code>apt-get:</code>:
+      <pre>apt-get install ia32-libs</pre>
+      </li>
+      <li>Next, install Java: <pre>apt-get install sun-java6-bin</pre></li>
+      <li>The Ubuntu package manager does not currently offer an Eclipse 3.3
+      version for download, so we recommend that you download Eclipse from
+      eclipse.org (<a
+      href="http://www.eclipse.org/downloads/">http://www.eclipse.org/
+      downloads/</a>). A Java or RCP version of Eclipse is recommended.</li>
+      <li>Follow the steps given in previous sections to install the SDK 
+      and the ADT plugin. </li>
+    </ol>
+  </li>
+</ul>
+
+<h3>Other Linux Notes</h3>
+
+<ul>
+  <li>If JDK is already installed on your development computer, please
+  take a moment to make sure that it meets the version requirements listed
+  in the <a href="{@docRoot}sdk/1.1_r1/requirements.html">System Requirements</a>.
+  In particular, note that some Linux distributions may include JDK 1.4 or Gnu
+  Compiler for Java, both of which are not supported for Android development.</li>
+</ul>
+
+
+
diff --git a/docs/html/sdk/1.5_r2/requirements.jd b/docs/html/sdk/1.5_r2/requirements.jd
new file mode 100644
index 0000000..4ed38a7
--- /dev/null
+++ b/docs/html/sdk/1.5_r2/requirements.jd
@@ -0,0 +1,39 @@
+page.title=System Requirements
+@jd:body
+
+<p>The sections below describe the system and software requirements for developing Android applications using the Android SDK tools included in Android <?cs var:sdk.version ?> SDK, Release <?cs var:sdk.rel.id ?>. </p>
+
+<h3>Supported Operating Systems</h3>
+<ul>
+  <li>Windows XP (32-bit) or Vista (32- or 64-bit)</li>
+  <li>Mac OS X 10.4.8 or later (x86 only)</li>
+  <li>Linux (tested on Linux Ubuntu Dapper Drake)</li>
+</ul>
+
+<h3>Supported Development Environments</h3>
+<ul>
+  <li>Eclipse IDE
+    <ul>
+      <li><a href="http://www.eclipse.org/downloads/">Eclipse</a> 3.3 (Europa), 3.4 (Ganymede)
+        <ul>
+        <li>Recommended Eclipse IDE packages: Eclipse IDE for Java EE Developers, Eclipse IDE for Java Developers, Eclipse for RCP/Plug-in Developers</li>
+        <li>Eclipse <a href="http://www.eclipse.org/jdt">JDT</a> plugin (included in most Eclipse IDE packages) </li>
+        <li>Eclipse Classic IDE package is not supported.</li>
+        </ul>
+      </li>     
+      <li><a href="http://java.sun.com/javase/downloads/index.jsp">JDK 5 or JDK 6</a> (JRE alone is not sufficient)</li>
+      <li><a href="installing.html#installingplugin">Android Development Tools plugin</a> (optional)</li>
+      <li><strong>Not</strong> compatible with Gnu Compiler for Java (gcj)</li>
+    </ul>
+  </li>
+  <li>Other development environments or IDEs
+    <ul>
+      <li><a href="http://java.sun.com/javase/downloads/index.jsp">JDK 5 or JDK 6</a> (JRE alone is not sufficient)</li>
+      <li><a href="http://ant.apache.org/">Apache Ant</a> 1.6.5 or later for Linux and Mac, 1.7 or later for Windows</li>
+      <li><strong>Not</strong> compatible with Gnu Compiler for Java (gcj)</li>
+    </ul>
+  </li>
+</ul>
+
+<p class="note"><strong>Note:</strong> If JDK is already installed on your development computer, please take a moment to make sure that it meets the version requirements listed above. In
+particular, note that some Linux distributions may include JDK 1.4 or Gnu Compiler for Java, both of which are not supported for Android development. </p>
\ No newline at end of file
diff --git a/docs/html/sdk/1.5_r2/upgrading.jd b/docs/html/sdk/1.5_r2/upgrading.jd
new file mode 100644
index 0000000..bb5fc60
--- /dev/null
+++ b/docs/html/sdk/1.5_r2/upgrading.jd
@@ -0,0 +1,395 @@
+page.title=Upgrading the SDK
+sdk.version=1.5_r2
+@jd:body
+
+
+<div id="qv-wrapper">
+<div id="qv">
+
+  <h2>Upgrading the SDK</h2>
+  <ul>
+    <li>The Android 1.5 SDK uses a new project structure and a new ADT plugin (ADT 0.9). </li>
+    <li>To move existing projects into the SDK, you must make some minor changes in your 
+    development environment.</li>
+    <li>The new ADT plugin (ADT 0.9) <em>is not compatible</em> with projects created in previous SDKs.</li>
+    <li>You need to uninstall your existing ADT plugin, before installing ADT 0.9.</li>
+  </ul>
+
+  <h2>In this document</h2>
+  <ol>
+    <li><a href="#Install">Install the SDK</a></li>
+    <li><a href="#UpdateAdt">Update Your Eclipse ADT Plugin</a></li>
+    <li><a href="#UpdateYourProjects">Update Your Projects</a>
+      <ol>
+        <li><a href="#EclipseUsers">Eclipse Users</a></li>
+        <li><a href="#AntUsers">Ant Users</a></li>
+      </ol>
+    </li>
+    <li><a href="#MigrateYourApplications">Migrate Your Applications</a>
+      <ol><li><a href="#FutureProofYourApps">Future-proof your apps</a></li></ol>
+    </li>
+  </ol>
+  
+  <h2>Migrating references</h2>
+  <ol>
+    <li><a href="{@docRoot}sdk/api_diff/3/changes.html">Android 1.5 API Differences</a></li>
+    <li><a 
+href="http://android-developers.blogspot.com/2009/04/future-proofing-your-apps.html">Future-Proofing
+Your Apps &raquo;</a></li>
+    <li><a 
+href="http://android-developers.blogspot.com/2009/04/ui-framework-changes-in-android-15.html">UI 
+framework changes in Android 1.5 &raquo;</a></li>
+  </ol>
+
+</div>
+</div>
+
+<p>This document describes how to move your development environment and existing
+Android applications from an Android 1.0 or 1.1 SDK to the Android 1.5 SDK.
+If you are migrating applications from an SDK older than 1.0, please also read the upgrading
+document available in the Android 1.0 SDK package.</p>
+
+<p>There are several compelling reasons to upgrade, such as new SDK tools
+that make developing more efficient and new APIs that allow you to expand the feature-set
+of your applications. However, even if you or your applications don't require these enhancements,
+it's important that you upgrade to ensure that your applications run properly on the 
+Android 1.5 platform.</p>
+
+<p>The Android 1.5 platform will soon be deployable to devices around the world.
+If you have already released Android applications to the public, you should
+test the forward-compatibility of your applications on the latest version of the platform
+as soon as possible. It's unlikely that you'll encounter breakage in your applications, but
+in the interest of maintaining the best user experience, you should take no risks.
+So, please install the new Android SDK and test your applications on Android 1.5.</p>
+
+<p>For more information on new SDK features and system changes, 
+see the <a href="{@docRoot}sdk/android-1.5.html">Android 1.5 Version Notes</a>.</p>
+
+
+<h2 id="Install">Install the SDK</h2>
+
+<p>If you haven't yet downloaded the SDK, <a href="{@docRoot}sdk/1.5_r2/index.html">download from here</a> 
+and unpack it into a safe location.</p>
+
+<p><strong>Before you begin:</strong>
+If you had previously setup your PATH variable to point to the SDK tools directory, 
+then you need to update it to point to the new SDK. For example, for a 
+<code>.bashrc</code> or <code>.bash_profile</code> file:</p>
+<pre>export PATH=$PATH:<em>&lt;your_sdk_dir></em>/tools</pre>
+
+<p>If you don't use Eclipse for development,
+skip to <a href="#updateYourProjects">Update Your Projects</a>.</p>
+
+
+<h2 id="UpdateAdt">Update Your Eclipse ADT Plugin</h2>
+
+<p><em>If you installed ADT-0.9_pre with the early look 1.5 SDK, there have been
+additional changes, so please continue with this guide and update to the final ADT 0.9.</em></p>
+
+<p>A new ADT plugin (version 0.9) is required for the Android 1.5 SDK.
+Because the component structure has been changed since Android 1.1, 
+the Android 1.5 SDK does not work with ADT 0.8 (or older) and previously installed SDKs will not
+work with ADT 0.9. However, the Android 1.5 SDK includes an Android 1.1 SDK image that you
+can build against while using ADT 0.9. </p>
+
+<p class="note">For information about using different system images (such as Android 1.1) 
+while running this SDK, see Developing <a href="{@docRoot}guide/developing/eclipse-adt.html">
+In Eclipse, with ADT</a> or <a href="{@docRoot}guide/developing/other-ide.html">In 
+Other IDEs</a>, as appropriate for your development environment.</p>
+
+<p>In order to upgrade your Eclipse IDE to use the new 0.9 ADT, follow the steps below
+for your respective version of Eclipse.</p>
+
+<h3 id="uninstallAdt">Uninstall your previous ADT plugin</h3>
+
+<p>You must uninstall your existing ADT plugin (0.8 or older). If you do not uninstall it,
+you will get a conflict with the Android Editors when installing the new ADT.
+(If you have already installed ADT-0.9_pre with the early look 1.5 SDK, you can skip this
+uninstall procedure and continue to <a href="#installAdt">Install the 0.9 ADT plugin</a>).</p>
+
+<table style="font-size:100%">
+<tr><th>Eclipse 3.3 (Europa)</th><th>Eclipse 3.4 (Ganymede)</th></tr>
+<tr>
+<td width="50%">
+<!-- 3.3 steps -->
+<ol>
+    <li>Select <strong>Help</strong> &gt; <strong>Software Updates</strong> &gt; 
+      <strong>Manage Configuration</strong>. </li>
+    <li>Expand the list in the left panel to reveal the installed tools.</li>
+    <li>Right-click "Android Editors" and click <strong>Uninstall</strong>. Click <strong>OK</strong> 
+    to confirm.</li>
+    <li>Restart Eclipse. 
+      <p>(Do not uninstall "Android Development Tools".)</p></li>
+</ol>
+</td>
+<td>
+<!-- 3.4 steps -->
+<ol>
+    <li>Select <strong>Help</strong> &gt; <strong>Software Updates</strong>.</li>
+    <li>Select the <strong>Installed Software</strong> tab.</li>
+    <li>Select "Android Editors". Click <strong>Uninstall</strong>.</li>
+    <li>In the next window, be sure "Android Editors" is checked, then click <strong>Finish</strong>
+    to uninstall.</li>
+    <li>Restart Eclipse.
+      <p>(Do not uninstall "Android Development Tools".)</p></li>
+</ol>
+</td>
+</tr>
+</table>
+
+
+<h3 id="installAdt">Install the 0.9 ADT plugin</h3>
+
+<p>Only install the new plugin once you've completed the procedure to
+<a href="#uninstallAdt">Uninstall your previous ADT plugin</a>.</p>
+
+<table style="font-size:100%">
+<tr><th>Eclipse 3.3 (Europa)</th><th>Eclipse 3.4 (Ganymede)</th></tr>
+<tr>
+<td width="50%">
+<!-- 3.3 steps -->
+<ol>
+    <li>Select <strong>Help</strong> &gt; <strong>Software Updates</strong> &gt; 
+      <strong>Find and Install</strong>. </li>
+    <li>Select <strong>Search for new features to install</strong>.</li>
+    <li>Select the Android plugin entry by checking the box next to it, 
+      then click <strong>Finish</strong>.
+      <p>(Your original entry for the plugin should still be here. If not, see the guide
+      to <a href="{@docRoot}sdk/1.5_r2/installing.html#installingplugin">Installing the ADT Plugin</a>.)
+      </p></li>
+    <li>In the results, expand the entry for the Android plugin and
+      be sure that "Developer Tools" is checked, then click <strong>Next</strong>.
+      (This will install "Android DDMS" and "Android Development Tools".)</li>
+    <li>Read and accept the license agreement, then click <strong>Next</strong>.
+    <li>In the next window, click <strong>Finish</strong> to start installation.</li>
+    <li>The ADT plugin is not digitally signed. Accept the installation anyway by clicking 
+    <strong>Install All</strong>.</li>
+    <li>Restart Eclipse.</li>
+</ol>
+</td>
+<td>
+<!-- 3.4 steps -->
+<ol>
+    <li>Select <strong>Help</strong> &gt; <strong>Software Updates</strong>.</li>
+    <li>Select the <strong>Available Software</strong> tab.</li>
+    <li>Expand the entry for the Andriod plugin (may be listed as the location URL)
+      and select "Developer Tools" by checking the box next to it, then click 
+      <strong>Install</strong>.</li>
+    <li>On the next window, "Android DDMS" and "Android Development Tools" 
+    should both be checked. Click <strong>Finish</strong>.</li>
+    <li>Restart Eclipse.</li>
+</ol>
+</td>
+</tr>
+</table>
+
+<p>If you encounter problems, ensure your ADT is fully uninstalled and then
+follow the guide to 
+<a href="{@docRoot}sdk/1.5_r2/installing.html#installingplugin">Installing the ADT Plugin
+for Eclipse</a>.</p>
+
+<h3 id="updateEclipsePrefs">Update your Eclipse SDK Preferences</h3>
+
+<p>The last step is to update your Eclipse preferences to point to the new SDK directory:</p>
+    <ol>
+      <li>Select <strong>Window</strong> > <strong>Preferences</strong> to open the Preferences 
+      panel (Mac: <strong>Eclipse</strong> > <strong>Preferences</strong>).</li>
+      <li>Select <strong>Android</strong> from the left panel.</li>
+      <li>For the <em>SDK Location</em> in the main panel, click <strong>Browse</strong> 
+      and locate your SDK directory.</li>
+      <li>Click <strong>Apply</strong>, then <strong>OK</strong>.</li>
+    </ol>
+
+
+<h2 id="UpdateYourProjects">Update Your Projects</h2>
+
+<p>You will now need to update any and all Android projects that you have
+developed using a previous version of the Android SDK.</p>
+
+
+<h3 id="EclipseUsers">Eclipse users</h3>
+
+<p>If you use Eclipse to develop applications, use the following procedure to 
+update each project:</p>
+
+<ol>
+  <li>Right-click on the individual project (in the Package Explorer)
+   and select <strong>Properties</strong>.</li>
+  <li>In the properties, open the Android panel and select a "build target" to compile 
+    against. This SDK offers the Android 1.1 and Android 1.5 platforms to choose from. When 
+    you are initially updating your projects to the new SDK, we recommend that you select a build 
+    target with the Android 1.1 platform. Click <strong>Apply</strong>, then 
+    <strong>OK</strong>.</li>
+</ol>
+
+<p>The new plugin creates a <code>gen/</code> folder in your project, in which it puts the 
+<code>R.java</code> file
+and all automatically generated AIDL java files. If you get an error such as 
+<code>The type R is already defined</code>, 
+then you probably need to delete your old <code>R.java</code> or your old auto-generated
+AIDL Java files in the <code>src/</code> folder.
+(This <em>does not</em> apply to your own hand-crafted parcelable AIDL java files.)</p>
+
+<p>Note that, with the Android 1.5 SDK, there is a new process for running 
+applications in the Android Emulator. 
+Specifically, you must create an Android Virtual Device (AVD) before you can launch an instance
+of the Emulator. Before attempting to run your applications with the new SDK, 
+please continue with the section below to 
+<a href="#MigrateYourApplications">Migrate Your Applications</a>.</p>
+
+
+<h3 id="AntUsers">Ant users</h3>
+
+<p>If you build your projects using the Ant tool (rather than with Eclipse), note the 
+following changes with the new SDK tools.</p>
+
+<h4>build.xml has changed</h4>
+
+<p>You must re-create your <code>build.xml</code> file.</p>
+
+<p>If you had customized your <code>build.xml</code>, first make a copy of it:</p>
+
+<pre>
+$ cd <em>my-project</em>
+$ cp build.xml build.xml.old
+</pre>
+
+<p>Now use the new <code>android</code> tool (located in <code><em>your_sdk</em>/tools/</code>) 
+to create a new <code>build.xml</code> that references 
+a specific platform target:</p>
+
+<pre>$ android update project --path /path/to/my-project --target 1</pre>
+
+<p>The "target" corresponds to an Android platform library (including any add-ons, such as 
+Google APIs) that you would like to build your project against. You can view a list of available 
+targets (and their corresponding integer ID) with the command, <code>android list targets</code>. 
+When you are initially updating your projects to the new SDK, we recommend that you select the 
+first target ("1"), which uses the Android 1.1 platform library.</p>
+
+<p>A <code>gen/</code> folder will be created the first time you build and your <code>R.java</code> and
+your AIDL Java files will be generated in here. You <strong>must</strong> remove
+the old <code>R.java</code> and old auto-generated AIDL java files from the 
+<code>src/</code> folder. (This
+does not apply to your own hand-crafted parcelabe AIDL java files.)</p>
+
+<p class="note"><strong>Note:</strong> The "activitycreator" tool has been replaced 
+by the new "android" tool. For information on creating new projects with the android tool,
+see the documentation about <a href="{@docRoot}guide/developing/other-ide.html">Developing 
+In Other IDEs</a>.</p>
+
+<p>Note that, with the Android 1.5 SDK, there is a new process for running 
+applications in the Android Emulator. 
+Specifically, you must create an Android Virtual Device (AVD) before you can launch an instance
+of the Emulator. Before attempting to run your applications with the new SDK, 
+please continue with the section below to 
+<a href="#MigrateYourApplications">Migrate Your Applications</a>.</p>
+
+
+<h2 id="MigrateYourApplications">Migrate Your Applications</h2>
+
+<p>After you have completed the process above to <a href="#UpdateYourProjects">Update Your 
+Projects</a>, you are strongly encouraged to run each of your applications in an instance
+of the emulator running the Android 1.5 system image. It's possible (however, unlikely) 
+that you'll encounter some breakage in your application when you run your applications on
+the Android 1.5 system image. Whether you believe your application will be affected by 
+platform changes or not, it's very important that you test the application's 
+forward-compatibility on Android 1.5.</p>
+
+<p>To test forward-compatibility, simply run your existing application (as-is) on an Android
+Emulator that's running the Android 1.5 system image. The following procedure will guide
+you through the process to running your existing applications on an emulator. <em>Please read
+the following guide completely before you begin</em>.</p>
+
+<p>To test your application on an emulator running Android 1.5:</p>
+<ol>
+  <li><a href="#UpdateYourProjects">Update Your Project</a> (you should have done this 
+  already, in the section above).</li>
+  <li>Run your existing project, as-is, on an emulator running the Android 1.5 system image.
+    <p>As mentioned in the guide to <a href="#UpdateYourProjects">Update Your Projects</a>, 
+    you should have selected a "build
+    target" of "1", which compiles your application against the Android 1.1 system image, so there
+    should be no new errors in your code.</p>
+    <p>Eclipse users: follow the 
+    <a href="{@docRoot}guide/developing/eclipse-adt.html#Running">Eclipse guide to 
+    Running Your Application</a>.</p>
+    <p>Ant users: follow the 
+    <a href="{@docRoot}guide/developing/other-ide.html#Running">Ant guide to 
+    Running Your Application</a>
+    <p>During the procedure to Running Your Application, select a "deployment target" 
+    for the AVD that includes the Android 1.5 platform. 
+    If your application utilizes the Google Maps APIs (i.e.,
+    MapView), be certain to select a target that includes the Google APIs.</p>
+    <p>Once you complete the procedures to run your application in your respective environment,
+    linked above, return here.</p>
+  </li>
+  <li>With your application running in the emulator, perform all regular testing on the application
+  to ensure that it functions normally (in both landscape and portrait orientations).</li>
+</ol>
+
+<p>Chances are, your application runs just fine on the Android 1.5 platform &mdash; 
+new devices will be able to safely install and run your application and
+current users who update their devices will be able to continue using your application as usual.
+However, if something doesn't work the way you expect, then you might need to revisit
+your project and make any necessary changes to your code.</p>
+
+<p>You can check for code breakages caused by API changes by opening your project 
+in Eclipse, changing the "build target" to one using the Android 1.5 platform,
+and see where the ADT identifies errors in your code.</p>
+
+
+<h3 id="FutureProofYourApps">Future-proof your apps</h3>
+
+<p>There have been several API additions made for this release, but there have been
+very few actual API <em>changes</em>. Only a couple (relatively unused) elements 
+have been removed and a few have been deprecated, so your applications written with the 
+Android 1.1 system library should work just fine. However, 
+your application is more likely to encounter problems on Android 1.5
+if it performs any of the following:</p>
+
+<ul>
+  <li>Uses internal APIs. That is, APIs that are not officially supported
+  and not available in the reference documentation. Any un-official APIs are always subject
+  to change (which is why they're un-official) and some have indeed changed.
+  </li>
+  <li>Directly manipulates system settings. There are some settings (such as
+  GPS, data roaming, bluetooth and others) that used to be writable by 
+  applications but have been changed so that they can only be explicitly modified by the user
+  through the system settings. Refer to {@link android.provider.Settings.Secure}
+  to see which settings are now secured and cannot be directly changed by your application.
+  </li>
+  <li>Uses View hierarchies that are unreasonably deep (more than 10 or so levels) or 
+  broad (more than 30 total). View hierarchies this big have always been troublesome, but 
+  Android 1.5 is much more efficient at exposing this and your application may crash.
+  </li>
+  <li>Makes assumptions about the available hardware. With new support for soft keyboards,
+  not all devices will have full QWERTY keyboards on the hardware. So if your application
+  listens for special keypress events that only occur on a keypad, then your application
+  should degrade gracefully when there is no keyboard available.
+  </li>
+  <li>Performs its own layout orientation changes based on the acceletometer (or via other
+  sensors). Some devices running Android 1.5 will automatically rotate the orientation
+  (and all devices have the option to turn on auto-rotation), so if your application also
+  attempts to rotate the orientation, it can result in strange behavior. In addition, if your
+  application uses the accelerometer to detect shaking and you do not want to rotate the 
+  orientation, then you should lock the current orientation with 
+  <a href="{@docRoot}guide/topics/manifest/activity-element.html#screen">android:screenOrientation</a>.
+  </li>
+</ul>
+
+<p>Please read our blog post on <a 
+href="http://android-developers.blogspot.com/2009/04/future-proofing-your-apps.html">Future-Proofing
+Your Apps</a> for more information on the issues mentioned above.</p>
+
+<p>For information
+about other changes made to Android 1.5, refer to the following documents:</p>
+<ul>
+  <li><a href="{@docRoot}sdk/api_diff/3/changes.html">Android 1.5 API Differences</a></li>
+  <li><a href="{@docRoot}sdk/android-1.5.html#api-changes">Android 1.5 Version Notes</a></li> 
+  <li><a 
+href="http://android-developers.blogspot.com/2009/04/ui-framework-changes-in-android-15.html">UI 
+framework changes in Android 1.5 &raquo;</a></li>
+</ul>
+
+<p>If you have additional trouble updating your code, visit the 
+<a href="http://groups.google.com/group/android-developers">Android Developers Group</a>
+to seek help from other Android developers.</p>
diff --git a/docs/html/sdk/RELEASENOTES.jd b/docs/html/sdk/RELEASENOTES.jd
index c44cef3..f3a1951 100644
--- a/docs/html/sdk/RELEASENOTES.jd
+++ b/docs/html/sdk/RELEASENOTES.jd
@@ -3,8 +3,16 @@
 
 <p>This document provides version-specific information about Android SDK
 releases. For the latest known issues, please ensure that you're viewing this
-page at: 
-<a href="http://developer.android.com/sdk/RELEASENOTES.html">http://developer.android.com/sdk/RELEASENOTES.html</a>.</p>
+page at <a href="http://developer.android.com/sdk/RELEASENOTES.html">http://developer.android.com/sdk/RELEASENOTES.html</a>.</p>
+
+
+<h2 id="1.5_r2">Android 1.5 SDK, Release 2</h2>
+
+<p>This SDK release provides the same developer tools as the Android 1.5 SDK,
+Release 1, but provides an updated Android 1.5 system image that includes a
+security patch for the issue described in the oCert advisory below:</p>
+
+<p style="margin-left:2em;"><a href="http://www.ocert.org/advisories/ocert-2009-006.html">http://www.ocert.org/advisories/ocert-2009-006.html</a></p>
 
 <h2 id="1.5_r1">Android 1.5 SDK, Release 1</h2>
 
diff --git a/docs/html/sdk/android-1.5-highlights.jd b/docs/html/sdk/android-1.5-highlights.jd
index e6c4f88..ff64e8c 100644
--- a/docs/html/sdk/android-1.5-highlights.jd
+++ b/docs/html/sdk/android-1.5-highlights.jd
@@ -1,5 +1,4 @@
 page.title=Android 1.5 Platform Highlights
-sdk.version=1.5_r1
 @jd:body
 
 <p>
diff --git a/docs/html/sdk/older_releases.jd b/docs/html/sdk/older_releases.jd
index ff57a36..3c2bbd4 100644
--- a/docs/html/sdk/older_releases.jd
+++ b/docs/html/sdk/older_releases.jd
@@ -1,37 +1,67 @@
-page.title=Older Releases
+page.title=Other SDK Releases
 @jd:body
 
-<div class="special">
-  <strong>NOTICE:</strong>
-  <p>The SDKs listed on this page are "early-look" versions that were released in
+<p>This page provides a full list of older, obsolete SDK releases, including
+non-current versions of active releases and "early look" versions that were
+released before Android 1.0. The list is provided for informational purposes
+only.</p>
+
+<p>If you are just getting started developing on Android, make sure that you
+are using the <a href="{@docRoot}sdk/{@sdkCurrent}/index.html">most current SDK available</a>,
+to ensure that your applications will be compatible with the latest
+Android-powered devices.</p>
+
+<h2>Obsolete Releases</h2>
+
+<p>The table below lists Android SDK releases that have been superceded by an
+active release and that are now obsolete. If you are using one of these
+releases, please upgrade to the <a href="{@docRoot}sdk/index.html">current SDK
+release</a>.</p>
+
+ <table>
+  <tr>
+     <th>Release</td>
+     <th>Platform(s)</th>
+     <th>Date</td>
+     <th>Description</td>
+   </tr>
+   <tr>
+     <td><a href="{@docRoot}sdk/1.5_r1/index.html">Android 1.5 SDK, Release 1</a></td>
+     <td style="text-align:center;">Android 1.5<br>Android 1.1</td>
+     <td><em>April 2009</em></td>
+     <td>Replaced by Android 1.5 SDK, Release 2. <em><a href="RELEASENOTES.html#1.5_r1">Release notes</a></em></td>
+   </tr>
+   <tr class="alt">
+     <td><a href="{@docRoot}sdk/1.0_r1/index.html">Android 1.0 SDK, Release 1</a></td>
+     <td style="text-align:center;">Android 1.0</td>
+     <td><em>September 2008</em></td>
+     <td>Replaced by Android 1.0 SDK, Release 2. <em><a href="RELEASENOTES.html#1.0_r1">Release notes</a></em></td>
+   </tr>
+ </table>
+
+ <h2>Non-Compatible  Releases</h2>
+
+<!-- <div class="special"> -->
+<p>The SDKs listed below are "early-look" versions that were released in
   the year preceding the full release of Android 1.0 in September 2008. Because
   these early-look SDKs were released before the Android 1.0 API specification was
   finalized, they do not provide a compliant Android execution environment.
   Consequently, applications that you develop in these SDKs will not be able to
   run on any Android-powered devices.</p>
 
-  <p>If you have an older application that you built in one of the early-look SDKs,
-  you must migrate it to the Android
-  1.0 SDK (or later release) before you will be able to deploy it to
-  an Android-powered device. To help with this migration, each SDK package below
-  provides information about API changes from the previous version. You can find
-  the migration information in the documentation included in each SDK package.</p>
+<p>If you have an older application that you built in one of the early-look
+SDKs, you must migrate it to the Android 1.0 SDK (or later release) before you
+will be able to deploy it to an Android-powered device. To help with this
+migration, each SDK package below provides information about API changes from
+the previous version. You can find the migration information in the
+documentation included in each SDK package.</p>
+<!-- </div> -->
 
-  <p>If you are just getting started developing on Android, do not use one of these early-look
-  SDKs. Instead, develop using the most <a href="{@docRoot}sdk/index.html">current
-  SDK release</a> available, to ensure that your applications will be compatible
-  with Android-powered devices.</p>
-</div>
-
-
-
-
- <h2>Android 0.9 SDK beta</h2>
- <p><em>August 18, 2008 - <a href="OLD_RELEASENOTES.html#0.9_beta">Release Notes</a></em></p>
+<h4>Android SDK m5-rc15</h4>
+<p><em>August 18, 2008 - <a href="OLD_RELEASENOTES.html#0.9_beta">Release Notes</a></em></p>
  <table>
    <tr>
-     <th>Platform</th>
-     <th>Package</th>
+     <th colspan="2">Package</th>
      <th>Size</th>
      <th>MD5 Checksum</th>
    </tr>
@@ -58,15 +88,11 @@
    </tr>
  </table>
 
-
-
-
-<h2>Version m5-rc15</h2>
+<h4>Version m5-rc15</h4>
  <p><em>March 3, 2008 - <a href="OLD_RELEASENOTES.html#m5-rc15">Release Notes</a></em></p>
  <table>
    <tr>
-     <th>Platform</th>
-     <th>Package</th>
+     <th colspan="2">Package</th>
      <th>Size</th>
      <th>MD5 Checksum</th>
    </tr>
@@ -93,15 +119,11 @@
    </tr>
  </table>
 
-
-
-
- <h2>Version m5-rc14</h2>
+ <h4>Version m5-rc14</h4>
  <p><em>February 12, 2008 - <a href="OLD_RELEASENOTES.html#m5-rc14">Release Notes</a></em></p>
  <table>
    <tr>
-     <th>Platform</th>
-     <th>Package</th>
+     <th colspan="2">Package</th>
      <th>Size</th>
      <th>MD5 Checksum</th>
    </tr>
@@ -131,12 +153,11 @@
 
 
 
- <h2>Version m3-rc37a</h2>
+ <h4>Version m3-rc37a</h4>
  <p><em>December 14, 2007 - <a href="OLD_RELEASENOTES.html#m3-rc37a">Release Notes</a></em></p>
  <table>
    <tr>
-     <th>Platform</th>
-     <th>Package</th>
+     <th colspan="2">Package</th>
      <th>Size</th>
      <th>MD5 Checksum</th>
    </tr>
@@ -166,12 +187,11 @@
 
 
 
- <h2>Version m3-rc22a</h2>
+ <h4>Version m3-rc22a</h4>
  <p><em>November 16, 2007 - <a href="OLD_RELEASENOTES.html#m3-rc22a">Release Notes</a></em></p>
  <table>
    <tr>
-     <th>Platform</th>
-     <th>Package</th>
+     <th colspan="2">Package</th>
      <th>Size</th>
      <th>MD5 Checksum</th>
    </tr>
@@ -201,12 +221,11 @@
 
 
 
- <h2>Version m3-rc20a</h2>
+ <h4>Version m3-rc20a</h4>
  <p><em>November 12, 2007 - <a href="OLD_RELEASENOTES.html#m3-rc20a">Release Notes</a></em></p>
  <table>
    <tr>
-     <th>Platform</th>
-     <th>Package</th>
+     <th colspan="2">Package</th>
      <th>Size</th>
      <th>MD5 Checksum</th>
    </tr>
diff --git a/docs/html/sdk/preview/features.html b/docs/html/sdk/preview/features.html
index 392c089..a2f085c 100644
--- a/docs/html/sdk/preview/features.html
+++ b/docs/html/sdk/preview/features.html
@@ -133,10 +133,10 @@
   <li>
     <h2>Current SDK Release</h2>
     <ul>
-      <li><a href="/sdk/1.5_r1/index.html">Download</a></li>
-      <li><a href="/sdk/1.5_r1/installing.html">Installing</a></li>
-      <li><a href="/sdk/1.5_r1/upgrading.html">Upgrading</a></li>
-      <li><a href="/sdk/1.5_r1/requirements.html">System Requirements</a></li>
+      <li><a href="/sdk/1.5_r2/index.html">Download</a></li>
+      <li><a href="/sdk/1.5_r2/installing.html">Installing</a></li>
+      <li><a href="/sdk/1.5_r2/upgrading.html">Upgrading</a></li>
+      <li><a href="/sdk/1.5_r2/requirements.html">System Requirements</a></li>
     </ul>
     <ul>
       <li><a href="/sdk/terms.html">SDK Terms and Conditions</a></li>
@@ -154,8 +154,7 @@
     <ul>
       <li><a href="/sdk/1.1_r1/index.html">Android 1.1 SDK, r1</a></li>
       <li><a href="/sdk/1.0_r2/index.html">Android 1.0 SDK, r2</a></li>
-      <li><a href="/sdk/1.0_r1/index.html">Android 1.0 SDK, r1</a></li>
-      <li><a href="/sdk/older_releases.html">Older Releases</a></li>
+      <li><a href="/sdk/older_releases.html">Other Releases</a></li>
     </ul>
   </li>
 </ul>
@@ -185,16 +184,6 @@
 
 </div> <!-- end body-content --> 
 
-<script type="text/javascript">
-init(); /* initialize android-developer-docs.js */
-var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
-document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-</script>
-<script type="text/javascript">
-var pageTracker = _gat._getTracker("UA-5831155-1");
-pageTracker._trackPageview();
-</script>
-
 </body>
 </html>
 
diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs
index 4b55b56..2079dd8 100644
--- a/docs/html/sdk/sdk_toc.cs
+++ b/docs/html/sdk/sdk_toc.cs
@@ -27,18 +27,11 @@
     </ul>
   </li>
   <li>
-    <h2>Native Development Tools</h2>
-    <ul>
-      <li><a href="<?cs var:toroot ?>sdk/ndk/1.5-r1/index.html">Android 1.5 NDK, r1</a></li>
-    </ul>
-  </li>
-  <li>
     <h2>Previous SDK Releases</h2>
     <ul>
       <li><a href="<?cs var:toroot ?>sdk/1.1_r1/index.html">Android 1.1 SDK, r1</a></li>
       <li><a href="<?cs var:toroot ?>sdk/1.0_r2/index.html">Android 1.0 SDK, r2</a></li>
-      <li><a href="<?cs var:toroot ?>sdk/1.0_r1/index.html">Android 1.0 SDK, r1</a></li>
-      <li><a href="<?cs var:toroot ?>sdk/older_releases.html">Older Releases</a></li>
+      <li><a href="<?cs var:toroot ?>sdk/older_releases.html">Other Releases</a></li>
     </ul>
   </li><?cs 
  /if ?>
diff --git a/docs/html/shareables/icon_templates-v1.0.zip b/docs/html/shareables/icon_templates-v1.0.zip
new file mode 100644
index 0000000..3e64f9aa
--- /dev/null
+++ b/docs/html/shareables/icon_templates-v1.0.zip
Binary files differ
diff --git a/docs/html/sitemap.txt b/docs/html/sitemap.txt
index 5bb8cae..a227d09 100644
--- a/docs/html/sitemap.txt
+++ b/docs/html/sitemap.txt
@@ -75,6 +75,7 @@
 http://developer.android.com/guide/publishing/preparing.html
 http://developer.android.com/guide/publishing/publishing.html
 http://developer.android.com/guide/practices/ui_guidelines/index.html
+http://developer.android.com/guide/practices/ui_guidelines/icon_design.html
 http://developer.android.com/guide/practices/ui_guidelines/widget_design.html
 http://developer.android.com/guide/practices/design/performance.html
 http://developer.android.com/guide/practices/design/responsiveness.html
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index 9087c44..af1490a 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -80,8 +80,11 @@
     status_t            writeStrongBinder(const sp<IBinder>& val);
     status_t            writeWeakBinder(const wp<IBinder>& val);
 
-    // doesn't take ownership of the native_handle
-    status_t            writeNativeHandle(const native_handle& handle);
+    // Place a native_handle into the parcel (the native_handle's file-
+    // descriptors are dup'ed, so it is safe to delete the native_handle
+    // when this function returns). 
+    // Doesn't take ownership of the native_handle.
+    status_t            writeNativeHandle(const native_handle* handle);
     
     // Place a file descriptor into the parcel.  The given fd must remain
     // valid for the lifetime of the parcel.
@@ -114,12 +117,11 @@
     wp<IBinder>         readWeakBinder() const;
 
     
-    // if alloc is NULL, native_handle is allocated with malloc(), otherwise
-    // alloc is used. If the function fails, the effects of alloc() must be
-    // reverted by the caller.
-    native_handle*     readNativeHandle(
-            native_handle* (*alloc)(void* cookie, int numFds, int ints),
-            void* cookie) const;
+    // Retrieve native_handle from the parcel. This returns a copy of the
+    // parcel's native_handle (the caller takes ownership). The caller
+    // must free the native_handle with native_handle_close() and 
+    // native_handle_delete().
+    native_handle*     readNativeHandle() const;
 
     
     // Retrieve a file descriptor from the parcel.  This returns the raw fd
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index e962db6e..106807e 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -39,10 +39,15 @@
 {
 public:
 
-    enum stream_type {
+    // input sources values must always be defined in the range
+    // [AudioRecord::DEFAULT_INPUT, AudioRecord::NUM_INPUT_SOURCES[
+    enum input_source {
         DEFAULT_INPUT   =-1,
         MIC_INPUT       = 0,
-        NUM_STREAM_TYPES
+        VOICE_UPLINK_INPUT = 1,
+        VOICE_DOWNLINK_INPUT = 2,
+        VOICE_CALL_INPUT = 3,
+        NUM_INPUT_SOURCES
     };
 
     static const int DEFAULT_SAMPLE_RATE = 8000;
@@ -118,7 +123,7 @@
      *
      * Parameters:
      *
-     * streamType:         Select the audio input to record to (e.g. AudioRecord::MIC_INPUT).
+     * inputSource:        Select the audio input to record to (e.g. AudioRecord::MIC_INPUT).
      * sampleRate:         Track sampling rate in Hz.
      * format:             PCM sample format (e.g AudioSystem::PCM_16_BIT for signed
      *                     16 bits per sample).
@@ -140,7 +145,7 @@
          RECORD_IIR_ENABLE = AudioSystem::TX_IIR_ENABLE
      };
 
-                        AudioRecord(int streamType,
+                        AudioRecord(int inputSource,
                                     uint32_t sampleRate = 0,
                                     int format          = 0,
                                     int channelCount    = 0,
@@ -165,7 +170,7 @@
      *  - NO_INIT: audio server or audio hardware not initialized
      *  - PERMISSION_DENIED: recording is not allowed for the requesting process
      * */
-            status_t    set(int streamType      = 0,
+            status_t    set(int inputSource     = 0,
                             uint32_t sampleRate = 0,
                             int format          = 0,
                             int channelCount    = 0,
@@ -197,6 +202,7 @@
             int         channelCount() const;
             uint32_t    frameCount() const;
             int         frameSize() const;
+            int         inputSource() const;
 
 
     /* After it's created the track is not active. Call start() to
@@ -323,7 +329,8 @@
     audio_track_cblk_t*     mCblk;
     uint8_t                 mFormat;
     uint8_t                 mChannelCount;
-    uint8_t                 mReserved[2];
+    uint8_t                 mInputSource;
+    uint8_t                 mReserved;
     status_t                mStatus;
     uint32_t                mLatency;
 
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
index 031335e..bac3d29 100644
--- a/include/media/IAudioFlinger.h
+++ b/include/media/IAudioFlinger.h
@@ -54,7 +54,7 @@
 
     virtual sp<IAudioRecord> openRecord(
                                 pid_t pid,
-                                int streamType,
+                                int inputSource,
                                 uint32_t sampleRate,
                                 int format,
                                 int channelCount,
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index b9ea0c6..aebe191 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -35,6 +35,10 @@
 enum audio_source {
     AUDIO_SOURCE_DEFAULT = 0,
     AUDIO_SOURCE_MIC = 1,
+    AUDIO_SOURCE_VOICE_UPLINK = 2,
+    AUDIO_SOURCE_VOICE_DOWNLINK = 3,
+    AUDIO_SOURCE_VOICE_CALL = 4,
+    AUDIO_SOURCE_MAX = AUDIO_SOURCE_VOICE_CALL
 };
 
 enum video_source {
diff --git a/include/tts/TtsEngine.h b/include/tts/TtsEngine.h
new file mode 100644
index 0000000..06f3820
--- /dev/null
+++ b/include/tts/TtsEngine.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2009 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <media/AudioSystem.h>
+
+// This header defines the interface used by the Android platform
+// to access Text-To-Speech functionality in shared libraries that implement speech
+// synthesis and the management of resources associated with the synthesis.
+// An example of the implementation of this interface can be found in 
+// FIXME: add path+name to implementation of default TTS engine
+// Libraries implementing this interface are used in:
+//  frameworks/base/tts/jni/android_tts_SpeechSynthesis.cpp
+
+namespace android {
+
+// The callback is used by the implementation of this interface to notify its
+// client, the Android TTS service, that the last requested synthesis has been
+// completed.
+// The callback for synthesis completed takes:
+//    void *       - The userdata pointer set in the original synth call
+//    uint32_t     - Track sampling rate in Hz
+//    audio_format - The AudioSystem::audio_format enum
+//    int          - The number of channels
+//    int8_t *     - A buffer of audio data only valid during the execution of the callback
+//    size_t       - The size of the buffer
+// Note about memory management:
+//    The implementation of TtsEngine is responsible for the management of the memory
+//    it allocates to store the synthesized speech. After the execution of the callback
+//    to hand the synthesized data to the client of TtsEngine, the TTS engine is
+//    free to reuse or free the previously allocated memory.
+//    This implies that the implementation of the "synthDoneCB" callback cannot use
+//    the pointer to the buffer of audio samples outside of the callback itself.
+typedef void (synthDoneCB_t)(void *, uint32_t, AudioSystem::audio_format, int, int8_t *, size_t);
+
+class TtsEngine;
+extern "C" TtsEngine* getTtsEngine();
+
+enum tts_result {
+    TTS_SUCCESS                 = 0,
+    TTS_FAILURE                 = -1,
+    TTS_FEATURE_UNSUPPORTED     = -2,
+    TTS_VALUE_INVALID           = -3,
+    TTS_PROPERTY_UNSUPPORTED    = -4,
+    TTS_PROPERTY_SIZE_TOO_SMALL = -5
+};
+
+class TtsEngine
+{
+public:
+    // Initialize the TTS engine and returns whether initialization succeeded.
+    // @param synthDoneCBPtr synthesis callback function pointer
+    // @return TTS_SUCCESS, or TTS_FAILURE
+    virtual tts_result init(synthDoneCB_t synthDoneCBPtr);
+
+    // Shut down the TTS engine and releases all associated resources.
+    // @return TTS_SUCCESS, or TTS_FAILURE
+    virtual tts_result shutdown();
+
+    // Interrupt synthesis and flushes any synthesized data that hasn't been output yet.
+    // This will block until callbacks underway are completed.
+    // @return TTS_SUCCESS, or TTS_FAILURE
+    virtual tts_result stop();
+
+    // Load the resources associated with the specified language. The loaded language will
+    // only be used once a call to setLanguage() with the same language value is issued.
+    // Language values are based on the Android conventions for localization as described in
+    // the Android platform documentation on internationalization. This implies that language
+    // data is specified in the format xx-rYY, where xx is a two letter ISO 639-1 language code
+    // in lowercase and rYY is a two letter ISO 3166-1-alpha-2 language code in uppercase
+    // preceded by a lowercase "r".
+    // @param value pointer to the language value
+    // @param size  length of the language value
+    // @return TTS_SUCCESS, or TTS_FAILURE
+    virtual tts_result loadLanguage(const char *value, const size_t size);
+
+    // Signal the engine to use the specified language. This will force the language to be
+    // loaded if it wasn't loaded previously with loadLanguage().
+    // See loadLanguage for the specification of the language.
+    // @param value pointer to the language value
+    // @param size  length of the language value
+    // @return TTS_SUCCESS, or TTS_FAILURE
+    virtual tts_result setLanguage(const char *value, const size_t size);
+
+    // Retrieve the currently set language, or an empty "value" if no language has
+    // been set.
+    // @param[out]   value pointer to the retrieved language value
+    // @param[inout] iosize  in: stores the size available to store the language value in *value
+    //                       out: stores the size required to hold the language value if
+    //                         getLanguage() returned  TTS_PROPERTY_SIZE_TOO_SMALL,
+    //                         unchanged otherwise.
+    // @return TTS_SUCCESS, or TTS_PROPERTY_SIZE_TOO_SMALL, or TTS_FAILURE
+    virtual tts_result getLanguage(char *value, size_t *iosize);
+
+    // Set a property for the the TTS engine
+    // "size" is the maximum size of "value" for properties "property"
+    // @param property pointer to the property name
+    // @param value    pointer to the property value
+    // @param size     maximum size required to store this type of property
+    // @return         TTS_PROPERTY_UNSUPPORTED, or TTS_SUCCESS, or TTS_FAILURE, 
+    //                  or TTS_VALUE_INVALID
+    virtual tts_result setProperty(const char *property, const char *value, const size_t size);
+
+    // Retrieve a property from the TTS engine
+    // @param        property pointer to the property name
+    // @param[out]   value    pointer to the retrieved language value
+    // @param[inout] iosize   in: stores the size available to store the property value
+    //                        out: stores the size required to hold the language value if
+    //                         getLanguage() returned  TTS_PROPERTY_SIZE_TOO_SMALL,
+    //                         unchanged otherwise.
+    // @return TTS_PROPERTY_UNSUPPORTED, or TTS_SUCCESS, or TTS_PROPERTY_SIZE_TOO_SMALL
+    virtual tts_result getProperty(const char *property, char *value, size_t *iosize);
+
+    // Synthesize the text.
+    // When synthesis completes, the engine invokes the callback to notify the TTS framework.
+    // Note about the format of the input: the text parameter may use the following elements
+    // and their respective attributes as defined in the SSML 1.0 specification:
+    //    * lang
+    //    * say-as:
+    //          o interpret-as
+    //    * phoneme
+    //    * voice:
+    //          o gender,
+    //          o age,
+    //          o variant,
+    //          o name
+    //    * emphasis
+    //    * break:
+    //          o strength,
+    //          o time
+    //    * prosody:
+    //          o pitch,
+    //          o contour,
+    //          o range,
+    //          o rate,
+    //          o duration,
+    //          o volume
+    //    * mark
+    // Differences between this text format and SSML are:
+    //    * full SSML documents are not supported
+    //    * namespaces are not supported
+    // Text is coded in UTF-8.
+    // @param text      the UTF-8 text to synthesize
+    // @param userdata  pointer to be returned when the call is invoked
+    // @return          TTS_SUCCESS or TTS_FAILURE
+    virtual tts_result synthesizeText(const char *text, void *userdata);
+
+    // Synthesize IPA text. When synthesis completes, the engine must call the given callback to notify the TTS API.
+    // @param ipa      the IPA data to synthesize
+    // @param userdata  pointer to be returned when the call is invoked
+    // @return TTS_FEATURE_UNSUPPORTED if IPA is not supported, otherwise TTS_SUCCESS or TTS_FAILURE
+    virtual tts_result synthesizeIpa(const char *ipa, void *userdata);
+};
+
+} // namespace android
+
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index 4b4fa5e..49b0129 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -1560,7 +1560,6 @@
 AudioFlinger::MixerThread::TrackBase::TrackBase(
             const sp<MixerThread>& mixerThread,
             const sp<Client>& client,
-            int streamType,
             uint32_t sampleRate,
             int format,
             int channelCount,
@@ -1570,7 +1569,6 @@
     :   RefBase(),
         mMixerThread(mixerThread),
         mClient(client),
-        mStreamType(streamType),
         mFrameCount(0),
         mState(IDLE),
         mClientTid(-1),
@@ -1720,12 +1718,13 @@
             int channelCount,
             int frameCount,
             const sp<IMemory>& sharedBuffer)
-    :   TrackBase(mixerThread, client, streamType, sampleRate, format, channelCount, frameCount, 0, sharedBuffer)
+    :   TrackBase(mixerThread, client, sampleRate, format, channelCount, frameCount, 0, sharedBuffer)
 {
     mVolume[0] = 1.0f;
     mVolume[1] = 1.0f;
     mMute = false;
     mSharedBuffer = sharedBuffer;
+    mStreamType = streamType;
 }
 
 AudioFlinger::MixerThread::Track::~Track()
@@ -1909,15 +1908,15 @@
 AudioFlinger::MixerThread::RecordTrack::RecordTrack(
             const sp<MixerThread>& mixerThread,
             const sp<Client>& client,
-            int streamType,
+            int inputSource,
             uint32_t sampleRate,
             int format,
             int channelCount,
             int frameCount,
             uint32_t flags)
-    :   TrackBase(mixerThread, client, streamType, sampleRate, format,
+    :   TrackBase(mixerThread, client, sampleRate, format,
                   channelCount, frameCount, flags, 0),
-        mOverflow(false)
+        mOverflow(false), mInputSource(inputSource)
 {
 }
 
@@ -2242,7 +2241,7 @@
 
 sp<IAudioRecord> AudioFlinger::openRecord(
         pid_t pid,
-        int streamType,
+        int inputSource,
         uint32_t sampleRate,
         int format,
         int channelCount,
@@ -2265,7 +2264,7 @@
         goto Exit;
     }
 
-    if (uint32_t(streamType) >= AudioRecord::NUM_STREAM_TYPES) {
+    if (uint32_t(inputSource) >= AudioRecord::NUM_INPUT_SOURCES) {
         LOGE("invalid stream type");
         lStatus = BAD_VALUE;
         goto Exit;
@@ -2308,7 +2307,7 @@
         frameCount = ((frameCount - 1)/inFrameCount + 1) * inFrameCount;
     
         // create new record track. The record track uses one track in mHardwareMixerThread by convention.
-        recordTrack = new MixerThread::RecordTrack(mHardwareMixerThread, client, streamType, sampleRate,
+        recordTrack = new MixerThread::RecordTrack(mHardwareMixerThread, client, inputSource, sampleRate,
                                                    format, channelCount, frameCount, flags);
     }
     if (recordTrack->getCblk() == NULL) {
@@ -2415,7 +2414,7 @@
                 LOGV("AudioRecordThread: loop starting");
                 if (mRecordTrack != 0) {
                     input = mAudioHardware->openInputStream(
-                                    mRecordTrack->type(),
+                                    mRecordTrack->inputSource(),
                                     mRecordTrack->format(), 
                                     mRecordTrack->channelCount(), 
                                     mRecordTrack->sampleRate(), 
diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h
index f3e6dc1..cc3d6c2 100644
--- a/libs/audioflinger/AudioFlinger.h
+++ b/libs/audioflinger/AudioFlinger.h
@@ -139,7 +139,7 @@
     // record interface
     virtual sp<IAudioRecord> openRecord(
                                 pid_t pid,
-                                int streamType,
+                                int inputSource,
                                 uint32_t sampleRate,
                                 int format,
                                 int channelCount,
@@ -232,7 +232,6 @@
 
                                 TrackBase(const sp<MixerThread>& mixerThread,
                                         const sp<Client>& client,
-                                        int streamType,
                                         uint32_t sampleRate,
                                         int format,
                                         int channelCount,
@@ -260,10 +259,6 @@
                 return mCblk;
             }
 
-            int type() const {
-                return mStreamType;
-            }
-
             int format() const {
                 return mFormat;
             }
@@ -293,7 +288,6 @@
             sp<Client>          mClient;
             sp<IMemory>         mCblkMemory;
             audio_track_cblk_t* mCblk;
-            int                 mStreamType;
             void*               mBuffer;
             void*               mBufferEnd;
             uint32_t            mFrameCount;
@@ -328,6 +322,11 @@
                     void        mute(bool);
                     void        setVolume(float left, float right);
 
+                    int type() const {
+                        return mStreamType;
+                    }
+
+
         protected:
             friend class MixerThread;
             friend class AudioFlinger;
@@ -364,6 +363,7 @@
             int8_t              mRetryCount;
             sp<IMemory>         mSharedBuffer;
             bool                mResetDone;
+            int                 mStreamType;
         };  // end of Track
 
         // record track
@@ -371,7 +371,7 @@
         public:
                                 RecordTrack(const sp<MixerThread>& mixerThread,
                                         const sp<Client>& client,
-                                        int streamType,
+                                        int inputSource,
                                         uint32_t sampleRate,
                                         int format,
                                         int channelCount,
@@ -385,6 +385,8 @@
                     bool        overflow() { bool tmp = mOverflow; mOverflow = false; return tmp; }
                     bool        setOverflow() { bool tmp = mOverflow; mOverflow = true; return tmp; }
 
+                    int         inputSource() const { return mInputSource; }
+
         private:
             friend class AudioFlinger;
             friend class AudioFlinger::RecordHandle;
@@ -397,6 +399,7 @@
             virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
 
             bool                mOverflow;
+            int                 mInputSource;
         };
 
         // playback track
diff --git a/libs/audioflinger/AudioHardwareGeneric.cpp b/libs/audioflinger/AudioHardwareGeneric.cpp
index a97c0bc..1e159b8 100644
--- a/libs/audioflinger/AudioHardwareGeneric.cpp
+++ b/libs/audioflinger/AudioHardwareGeneric.cpp
@@ -98,8 +98,8 @@
         status_t *status, AudioSystem::audio_in_acoustics acoustics)
 {
     // check for valid input source
-    if ((inputSource != AudioRecord::DEFAULT_INPUT) &&
-            (inputSource != AudioRecord::MIC_INPUT)) {
+    if ((inputSource < AudioRecord::DEFAULT_INPUT) ||
+        (inputSource >= AudioRecord::NUM_INPUT_SOURCES)) {
         return 0;
     }
 
diff --git a/libs/audioflinger/AudioHardwareStub.cpp b/libs/audioflinger/AudioHardwareStub.cpp
index c61e6e6..0ab4c60 100644
--- a/libs/audioflinger/AudioHardwareStub.cpp
+++ b/libs/audioflinger/AudioHardwareStub.cpp
@@ -61,8 +61,8 @@
         status_t *status, AudioSystem::audio_in_acoustics acoustics)
 {
     // check for valid input source
-    if ((inputSource != AudioRecord::DEFAULT_INPUT) &&
-            (inputSource != AudioRecord::MIC_INPUT)) {
+    if ((inputSource < AudioRecord::DEFAULT_INPUT) ||
+        (inputSource >= AudioRecord::NUM_INPUT_SOURCES)) {
         return 0;
     }
 
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index d29ec8c28..3747de6 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -409,12 +409,16 @@
             mObjects[idx++] = off;
             mObjectsSize++;
 
-            const flat_binder_object* flat
+            flat_binder_object* flat
                 = reinterpret_cast<flat_binder_object*>(mData + off);
             acquire_object(proc, *flat, this);
 
-            // take note if the object is a file descriptor
             if (flat->type == BINDER_TYPE_FD) {
+                // If this is a file descriptor, we need to dup it so the
+                // new Parcel now owns its own fd, and can declare that we
+                // officially know we have fds.
+                flat->handle = dup(flat->handle);
+                flat->cookie = (void*)1;
                 mHasFds = mFdsKnown = true;
             }
         }
@@ -650,28 +654,26 @@
     return flatten_binder(ProcessState::self(), val, this);
 }
 
-status_t Parcel::writeNativeHandle(const native_handle& handle)
+status_t Parcel::writeNativeHandle(const native_handle* handle)
 {
-    if (handle.version != sizeof(native_handle))
+    if (handle->version != sizeof(native_handle))
         return BAD_TYPE;
 
     status_t err;
-    err = writeInt32(handle.numFds);
+    err = writeInt32(handle->numFds);
     if (err != NO_ERROR) return err;
 
-    err = writeInt32(handle.numInts);
+    err = writeInt32(handle->numInts);
     if (err != NO_ERROR) return err;
 
-    for (int i=0 ; err==NO_ERROR && i<handle.numFds ; i++)
-        err = writeDupFileDescriptor(handle.data[i]);
+    for (int i=0 ; err==NO_ERROR && i<handle->numFds ; i++)
+        err = writeDupFileDescriptor(handle->data[i]);
 
     if (err != NO_ERROR) {
         LOGD("write native handle, write dup fd failed");
         return err;
     }
-
-    err = write(handle.data + handle.numFds, sizeof(int)*handle.numInts);
-
+    err = write(handle->data + handle->numFds, sizeof(int)*handle->numInts);
     return err;
 }
 
@@ -928,7 +930,7 @@
 }
 
 
-native_handle* Parcel::readNativeHandle(native_handle* (*alloc)(void*, int, int), void* cookie) const
+native_handle* Parcel::readNativeHandle() const
 {
     int numFds, numInts;
     status_t err;
@@ -937,30 +939,15 @@
     err = readInt32(&numInts);
     if (err != NO_ERROR) return 0;
 
-    native_handle* h;
-    if (alloc == 0) {
-        size_t size = sizeof(native_handle) + sizeof(int)*(numFds + numInts);
-        h = (native_handle*)malloc(size); 
-        h->version = sizeof(native_handle);
-        h->numFds = numFds;
-        h->numInts = numInts;
-    } else {
-        h = alloc(cookie, numFds, numInts);
-        if (h->version != sizeof(native_handle)) {
-            return 0;
-        }
-    }
+    native_handle* h = native_handle_create(numFds, numInts);
     for (int i=0 ; err==NO_ERROR && i<numFds ; i++) {
         h->data[i] = dup(readFileDescriptor());
         if (h->data[i] < 0) err = BAD_VALUE;
     }
-
     err = read(h->data + numFds, sizeof(int)*numInts);
-
     if (err != NO_ERROR) {
-        if (alloc == 0) {
-            free(h);
-        }
+        native_handle_close(h);
+        native_handle_delete(h);
         h = 0;
     }
     return h;
diff --git a/libs/rs/Android.mk b/libs/rs/Android.mk
new file mode 100644
index 0000000..83d3d66
--- /dev/null
+++ b/libs/rs/Android.mk
@@ -0,0 +1,133 @@
+# Only build if BUILD_RENDERSCRIPT is defined to true in the environment.
+ifeq ($(BUILD_RENDERSCRIPT),true)
+
+TOP_LOCAL_PATH:=$(call my-dir)
+include $(CLEAR_VARS)
+LOCAL_PATH:= $(TOP_LOCAL_PATH)
+
+# Build rsg-generator
+
+LOCAL_MODULE := rsg-generator
+
+# These symbols are normally defined by BUILD_XXX, but we need to define them
+# here so that local-intermediates-dir works.
+
+LOCAL_IS_HOST_MODULE := true
+LOCAL_MODULE_CLASS := EXECUTABLES
+intermediates:= $(local-intermediates-dir)
+
+GEN := $(addprefix $(intermediates)/, \
+            lex.yy.c \
+        )
+$(GEN):	PRIVATE_CUSTOM_TOOL = flex -o $@ $<
+
+$(intermediates)/lex.yy.c : $(LOCAL_PATH)/spec.lex
+	$(transform-generated-source)
+
+$(LOCAL_PATH)/rsg_generator.c : $(intermediates)/lex.yy.c
+
+LOCAL_SRC_FILES:= \
+    rsg_generator.c
+	
+include $(BUILD_HOST_EXECUTABLE)
+
+RSG_GENERATOR:=$(LOCAL_BUILT_MODULE)
+
+# Build render script lib
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libRS
+
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+intermediates:= $(local-intermediates-dir)
+
+RS_GENERATED_INCLUDE_DIR:=$(intermediates)
+
+# Generate custom headers
+
+GEN := $(addprefix $(intermediates)/, \
+            rsgApiStructs.h \
+            rsgApiFuncDecl.h \
+        )
+
+$(GEN) : PRIVATE_CUSTOM_TOOL = $(RSG_GENERATOR) $< $@ <$(TOP_LOCAL_PATH)/rs.spec
+$(GEN) : $(RSG_GENERATOR) $(LOCAL_PATH)/rs.spec
+$(GEN): $(intermediates)/%.h : $(LOCAL_PATH)/%.h.rsg
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+# Generate custom source files
+
+GEN := $(addprefix $(intermediates)/, \
+            rsgApi.cpp \
+            rsgApiReplay.cpp \
+        )
+        
+$(GEN) : PRIVATE_CUSTOM_TOOL = $(RSG_GENERATOR) $< $@ <$(TOP_LOCAL_PATH)/rs.spec
+$(GEN) : $(RSG_GENERATOR) $(LOCAL_PATH)/rs.spec
+$(GEN): $(intermediates)/%.cpp : $(LOCAL_PATH)/%.cpp.rsg
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+LOCAL_SRC_FILES:= \
+	rsAdapter.cpp \
+	rsAllocation.cpp \
+	rsComponent.cpp \
+	rsContext.cpp \
+	rsDevice.cpp \
+	rsElement.cpp \
+	rsLocklessFifo.cpp \
+	rsObjectBase.cpp \
+	rsMatrix.cpp \
+	rsProgram.cpp \
+	rsProgramFragment.cpp \
+	rsProgramFragmentStore.cpp \
+	rsProgramVertex.cpp \
+	rsSampler.cpp \
+	rsScript.cpp \
+	rsScriptC.cpp \
+	rsThreadIO.cpp \
+	rsType.cpp \
+	rsTriangleMesh.cpp
+
+LOCAL_SHARED_LIBRARIES += libcutils libutils libEGL libGLESv1_CM libui 
+LOCAL_LDLIBS := -lpthread -ldl
+LOCAL_MODULE:= libRS
+
+#LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_SHARED_LIBRARY)
+
+# Build JNI library
+
+LOCAL_PATH:= $(TOP_LOCAL_PATH)/jni
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+	RenderScript_jni.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+	libandroid_runtime \
+	libnativehelper \
+	libRS \
+	libcutils \
+	libutils \
+	libui
+
+LOCAL_STATIC_LIBRARIES :=
+
+LOCAL_C_INCLUDES += \
+	$(JNI_H_INCLUDE) \
+	$(RS_GENERATED_INCLUDE_DIR) \
+	$(call include-path-for, corecg graphics)
+
+LOCAL_CFLAGS +=
+
+LOCAL_LDLIBS := -lpthread
+
+LOCAL_MODULE:= libRS_jni
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(call all-subdir-makefiles)
+endif # BUILD_RENDERSCRIPT
diff --git a/libs/rs/RenderScript.h b/libs/rs/RenderScript.h
new file mode 100644
index 0000000..e1a4b6d
--- /dev/null
+++ b/libs/rs/RenderScript.h
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RENDER_SCRIPT_H
+#define RENDER_SCRIPT_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//////////////////////////////////////////////////////
+// 
+
+typedef void * RsAdapter1D;
+typedef void * RsAdapter2D;
+typedef void * RsAllocation;
+typedef void * RsContext;
+typedef void * RsDevice;
+typedef void * RsElement;
+typedef void * RsSampler;
+typedef void * RsScript;
+typedef void * RsScriptBasicTemp;
+typedef void * RsTriangleMesh;
+typedef void * RsType;
+
+typedef void * RsProgramVertex;
+typedef void * RsProgramFragment;
+typedef void * RsProgramFragmentStore;
+
+RsDevice rsDeviceCreate();
+void rsDeviceDestroy(RsDevice);
+
+RsContext rsContextCreate(RsDevice, void *, uint32_t version);
+void rsContextDestroy(RsContext);
+
+enum RsDataType {
+    RS_TYPE_FLOAT,
+    RS_TYPE_UNSIGNED,
+    RS_TYPE_SIGNED
+};
+
+enum RsDataKind {
+    RS_KIND_USER,
+    RS_KIND_RED, 
+    RS_KIND_GREEN, 
+    RS_KIND_BLUE, 
+    RS_KIND_ALPHA, 
+    RS_KIND_LUMINANCE, 
+    RS_KIND_INTENSITY,
+    RS_KIND_X, 
+    RS_KIND_Y, 
+    RS_KIND_Z, 
+    RS_KIND_W,
+    RS_KIND_S, 
+    RS_KIND_T, 
+    RS_KIND_Q, 
+    RS_KIND_R,
+    RS_KIND_NX, 
+    RS_KIND_NY, 
+    RS_KIND_NZ,
+    RS_KIND_INDEX
+};
+
+enum RsElementPredefined {
+    RS_ELEMENT_USER_U8,
+    RS_ELEMENT_USER_I8,
+    RS_ELEMENT_USER_U16,
+    RS_ELEMENT_USER_I16,
+    RS_ELEMENT_USER_U32,
+    RS_ELEMENT_USER_I32,
+    RS_ELEMENT_USER_FLOAT, 
+
+    RS_ELEMENT_RGB_565, 
+    RS_ELEMENT_RGBA_5551, 
+    RS_ELEMENT_RGBA_4444, 
+    RS_ELEMENT_RGB_888, 
+    RS_ELEMENT_RGBA_8888, 
+
+    RS_ELEMENT_INDEX_16, 
+    RS_ELEMENT_INDEX_32, 
+    RS_ELEMENT_XY_F32, 
+    RS_ELEMENT_XYZ_F32, 
+    RS_ELEMENT_ST_XY_F32, 
+    RS_ELEMENT_ST_XYZ_F32, 
+    RS_ELEMENT_NORM_XYZ_F32,
+    RS_ELEMENT_NORM_ST_XYZ_F32,
+};  
+
+enum RsSamplerParam {
+    RS_SAMPLER_MIN_FILTER,
+    RS_SAMPLER_MAG_FILTER,
+    RS_SAMPLER_WRAP_S,
+    RS_SAMPLER_WRAP_T,
+    RS_SAMPLER_WRAP_R
+};  
+
+enum RsSamplerValue {
+    RS_SAMPLER_NEAREST,
+    RS_SAMPLER_LINEAR,
+    RS_SAMPLER_LINEAR_MIP_LINEAR,
+    RS_SAMPLER_WRAP,
+    RS_SAMPLER_CLAMP
+};  
+
+enum RsDimension {
+    RS_DIMENSION_X,
+    RS_DIMENSION_Y,
+    RS_DIMENSION_Z,
+    RS_DIMENSION_LOD,
+    RS_DIMENSION_FACE,
+
+    RS_DIMENSION_ARRAY_0 = 100, 
+    RS_DIMENSION_ARRAY_1, 
+    RS_DIMENSION_ARRAY_2, 
+    RS_DIMENSION_ARRAY_3,
+    RS_DIMENSION_MAX = RS_DIMENSION_ARRAY_3
+};
+
+enum RsDepthFunc {
+    RS_DEPTH_FUNC_ALWAYS,
+    RS_DEPTH_FUNC_LESS,
+    RS_DEPTH_FUNC_LEQUAL,
+    RS_DEPTH_FUNC_GREATER,
+    RS_DEPTH_FUNC_GEQUAL,
+    RS_DEPTH_FUNC_EQUAL,
+    RS_DEPTH_FUNC_NOTEQUAL
+};
+
+enum RsBlendSrcFunc {
+    RS_BLEND_SRC_ZERO, 
+    RS_BLEND_SRC_ONE, 
+    RS_BLEND_SRC_DST_COLOR, 
+    RS_BLEND_SRC_ONE_MINUS_DST_COLOR, 
+    RS_BLEND_SRC_SRC_ALPHA, 
+    RS_BLEND_SRC_ONE_MINUS_SRC_ALPHA, 
+    RS_BLEND_SRC_DST_ALPHA, 
+    RS_BLEND_SRC_ONE_MINUS_DST_ALPHA, 
+    RS_BLEND_SRC_SRC_ALPHA_SATURATE
+};
+
+enum RsBlendDstFunc {
+    RS_BLEND_DST_ZERO, 
+    RS_BLEND_DST_ONE, 
+    RS_BLEND_DST_SRC_COLOR, 
+    RS_BLEND_DST_ONE_MINUS_SRC_COLOR, 
+    RS_BLEND_DST_SRC_ALPHA, 
+    RS_BLEND_DST_ONE_MINUS_SRC_ALPHA, 
+    RS_BLEND_DST_DST_ALPHA, 
+    RS_BLEND_DST_ONE_MINUS_DST_ALPHA
+};
+
+enum RsTexEnvMode {
+    RS_TEX_ENV_MODE_REPLACE,
+    RS_TEX_ENV_MODE_MODULATE,
+    RS_TEX_ENV_MODE_DECAL
+};
+
+
+
+#include "rsgApiFuncDecl.h"
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif // RENDER_SCRIPT_H
+
+
+
diff --git a/libs/rs/RenderScriptEnv.h b/libs/rs/RenderScriptEnv.h
new file mode 100644
index 0000000..9ba1a00
--- /dev/null
+++ b/libs/rs/RenderScriptEnv.h
@@ -0,0 +1,93 @@
+#include <stdint.h>
+
+
+typedef void * RsAdapter1D;
+typedef void * RsAdapter2D;
+typedef void * RsAllocation;
+typedef void * RsContext;
+typedef void * RsDevice;
+typedef void * RsElement;
+typedef void * RsSampler;
+typedef void * RsScript;
+typedef void * RsScriptBasicTemp;
+typedef void * RsTriangleMesh;
+typedef void * RsType;
+typedef void * RsProgramFragment;
+typedef void * RsProgramFragmentStore;
+
+
+typedef struct {
+    float m[16];
+} rsc_Matrix;
+
+
+typedef struct {
+    float v[4];
+} rsc_Vector4;
+
+#define RS_PROGRAM_VERTEX_MODELVIEW_OFFSET 0
+#define RS_PROGRAM_VERTEX_PROJECTION_OFFSET 16
+#define RS_PROGRAM_VERTEX_TEXTURE_OFFSET 32
+
+typedef struct {
+    const void * (*loadEnvVp)(void *con, uint32_t bank, uint32_t offset);
+
+    float (*loadEnvF)(void *con, uint32_t bank, uint32_t offset);
+    int32_t (*loadEnvI32)(void *con, uint32_t bank, uint32_t offset);
+    uint32_t (*loadEnvU32)(void *con, uint32_t bank, uint32_t offset);
+    void (*loadEnvVec4)(void *con, uint32_t bank, uint32_t offset, rsc_Vector4 *);
+    void (*loadEnvMatrix)(void *con, uint32_t bank, uint32_t offset, rsc_Matrix *);
+
+    void (*storeEnvF)(void *con, uint32_t bank, uint32_t offset, float);
+    void (*storeEnvI32)(void *con, uint32_t bank, uint32_t offset, int32_t);
+    void (*storeEnvU32)(void *con, uint32_t bank, uint32_t offset, uint32_t);
+    void (*storeEnvVec4)(void *con, uint32_t bank, uint32_t offset, const rsc_Vector4 *);
+    void (*storeEnvMatrix)(void *con, uint32_t bank, uint32_t offset, const rsc_Matrix *);
+
+    void (*matrixLoadIdentity)(void *con, rsc_Matrix *);
+    void (*matrixLoadFloat)(void *con, rsc_Matrix *, const float *);
+    void (*matrixLoadMat)(void *con, rsc_Matrix *, const rsc_Matrix *);
+    void (*matrixLoadRotate)(void *con, rsc_Matrix *, float rot, float x, float y, float z);
+    void (*matrixLoadScale)(void *con, rsc_Matrix *, float x, float y, float z);
+    void (*matrixLoadTranslate)(void *con, rsc_Matrix *, float x, float y, float z);
+    void (*matrixLoadMultiply)(void *con, rsc_Matrix *, const rsc_Matrix *lhs, const rsc_Matrix *rhs);
+    void (*matrixMultiply)(void *con, rsc_Matrix *, const rsc_Matrix *rhs);
+    void (*matrixRotate)(void *con, rsc_Matrix *, float rot, float x, float y, float z);
+    void (*matrixScale)(void *con, rsc_Matrix *, float x, float y, float z);
+    void (*matrixTranslate)(void *con, rsc_Matrix *, float x, float y, float z);
+
+    void (*color)(void *con, float r, float g, float b, float a);
+
+    void (*renderTriangleMesh)(void *con, RsTriangleMesh);
+    void (*renderTriangleMeshRange)(void *con, RsTriangleMesh, uint32_t start, uint32_t count);
+
+    void (*programFragmentBindTexture)(void *con, RsProgramFragment, uint32_t slot, RsAllocation);
+    void (*programFragmentBindSampler)(void *con, RsProgramFragment, uint32_t slot, RsAllocation);
+    
+    void (*materialDiffuse)(void *con, float r, float g, float b, float a);
+    void (*materialSpecular)(void *con, float r, float g, float b, float a);
+    void (*lightPosition)(void *con, float x, float y, float z, float w);
+    void (*materialShininess)(void *con, float s);
+
+    void (*uploadToTexture)(void *con, RsAllocation va, uint32_t baseMipLevel);
+
+    void (*enable)(void *con, uint32_t);
+    void (*disable)(void *con, uint32_t);
+
+    uint32_t (*rand)(void *con, uint32_t max);
+
+    // Assumes (GL_FIXED) x,y,z (GL_UNSIGNED_BYTE)r,g,b,a
+    void (*drawTriangleArray)(void *con, RsAllocation alloc, uint32_t count);
+
+    void (*contextBindProgramFragment)(void *con, RsProgramFragment pf);
+    void (*contextBindProgramFragmentStore)(void *con, RsProgramFragmentStore pfs);
+} rsc_FunctionTable;
+
+typedef void (*rsc_RunScript)(void *con, const rsc_FunctionTable *, uint32_t launchID);
+
+
+/* EnableCap */
+#define GL_LIGHTING                       0x0B50
+
+/* LightName */
+#define GL_LIGHT0                         0x4000
diff --git a/libs/rs/java/Android.mk b/libs/rs/java/Android.mk
new file mode 100644
index 0000000..5053e7d
--- /dev/null
+++ b/libs/rs/java/Android.mk
@@ -0,0 +1 @@
+include $(call all-subdir-makefiles)
diff --git a/libs/rs/java/Fountain/Android.mk b/libs/rs/java/Fountain/Android.mk
new file mode 100644
index 0000000..179009f
--- /dev/null
+++ b/libs/rs/java/Fountain/Android.mk
@@ -0,0 +1,31 @@
+#
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := Calc
+
+include $(BUILD_PACKAGE)
+##################################################
+include $(CLEAR_VARS)
+
+include $(BUILD_MULTI_PREBUILT)
+
+# Use the folloing include to make our test apk.
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/libs/rs/java/Fountain/AndroidManifest.xml b/libs/rs/java/Fountain/AndroidManifest.xml
new file mode 100644
index 0000000..8eee0663
--- /dev/null
+++ b/libs/rs/java/Fountain/AndroidManifest.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.calc">
+    <application android:label="Calc">
+        <activity android:name="Calc" 
+                  android:theme="@android:style/Theme.Black.NoTitleBar">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest> 
diff --git a/libs/rs/java/Fountain/src/com/android/fountain/Fountain.java b/libs/rs/java/Fountain/src/com/android/fountain/Fountain.java
new file mode 100644
index 0000000..94fdb8e
--- /dev/null
+++ b/libs/rs/java/Fountain/src/com/android/fountain/Fountain.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.calc;
+
+import android.app.Activity;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.provider.Settings.System;
+import android.util.Config;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.Window;
+import android.widget.Button;
+import android.widget.ListView;
+
+import java.lang.Runtime;
+
+public class Calc extends Activity {
+    //EventListener mListener = new EventListener();
+
+    private static final String LOG_TAG = "libRS_jni";
+    private static final boolean DEBUG  = false;
+    private static final boolean LOG_ENABLED = DEBUG ? Config.LOGD : Config.LOGV;
+
+    private CalcView mView;
+
+    // get the current looper (from your Activity UI thread for instance
+
+
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        // Create our Preview view and set it as the content of our
+        // Activity
+        mView = new CalcView(this);
+        setContentView(mView);
+    }
+
+    @Override
+    protected void onResume() {
+        // Ideally a game should implement onResume() and onPause()
+        // to take appropriate action when the activity looses focus
+        super.onResume();
+        mView.onResume();
+    }
+
+    @Override
+    protected void onPause() {
+        // Ideally a game should implement onResume() and onPause()
+        // to take appropriate action when the activity looses focus
+        super.onPause();
+        mView.onPause();
+
+        Runtime.getRuntime().exit(0);
+    }
+
+
+    static void log(String message) {
+        if (LOG_ENABLED) {
+            Log.v(LOG_TAG, message);
+        }
+    }
+
+
+}
+
diff --git a/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java b/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java
new file mode 100644
index 0000000..ecde910
--- /dev/null
+++ b/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.calc;
+
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.concurrent.Semaphore;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.KeyEvent; 
+import android.view.MotionEvent; 
+
+public class CalcView extends RSSurfaceView {
+
+    public CalcView(Context context) {
+        super(context);
+
+        //setFocusable(true);
+    }
+
+    private RenderScript mRS;
+    private RenderScript.Allocation mIntAlloc;
+    private RenderScript.Allocation mPartAlloc;
+    private RenderScript.Allocation mVertAlloc;
+    private RenderScript.Script mScript;
+    private RenderScript.ProgramFragmentStore mPFS;
+    private RenderScript.ProgramFragment mPF;
+
+    int mParams[] = new int[10];
+
+    private void initRS() {
+        mRS = createRenderScript();
+
+        int partCount = 1024;
+
+        mIntAlloc = mRS.allocationCreatePredefSized(RenderScript.ElementPredefined.USER_I32, 10);
+        mPartAlloc = mRS.allocationCreatePredefSized(RenderScript.ElementPredefined.USER_I32, partCount * 3 * 3);
+        mVertAlloc = mRS.allocationCreatePredefSized(RenderScript.ElementPredefined.USER_I32, partCount * 5 + 1);
+
+        mRS.programFragmentStoreBegin(null, null);
+        mRS.programFragmentStoreBlendFunc(RenderScript.BlendSrcFunc.SRC_ALPHA, RenderScript.BlendDstFunc.ONE);
+        mRS.programFragmentStoreDepthFunc(RenderScript.DepthFunc.ALWAYS);
+        mPFS = mRS.programFragmentStoreCreate();
+        mRS.contextBindProgramFragmentStore(mPFS);
+
+        mRS.programFragmentBegin(null, null);
+        mPF = mRS.programFragmentCreate();
+        mRS.contextBindProgramFragment(mPF);
+
+        mParams[0] = 0;
+        mParams[1] = partCount;
+        mParams[2] = 0;
+        mParams[3] = 0;
+        mParams[4] = 0;
+        mParams[5] = mPartAlloc.mID;
+        mIntAlloc.data(mParams);
+
+        int t2[] = new int[partCount * 4*3];
+        for (int ct=0; ct < t2.length; ct++) {
+            t2[ct] = 0;
+        }
+        mPartAlloc.data(t2);
+
+        mRS.scriptCBegin();
+        mRS.scriptCSetClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+        mRS.scriptCSetScript("");
+        mRS.scriptCSetRoot(true);
+        mScript = mRS.scriptCCreate();
+
+        mScript.bindAllocation(mIntAlloc, 0);
+        mScript.bindAllocation(mPartAlloc, 1);
+        mScript.bindAllocation(mVertAlloc, 2);
+        mRS.contextBindRootScript(mScript);
+
+    }
+
+    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+        super.surfaceChanged(holder, format, w, h);
+
+        initRS();
+    }
+
+    @Override 
+    public boolean onKeyDown(int keyCode, KeyEvent event) 
+    { 
+        // break point at here 
+        // this method doesn't work when 'extends View' include 'extends ScrollView'. 
+        return super.onKeyDown(keyCode, event); 
+    } 
+
+    int mTouchAction;
+
+    @Override 
+    public boolean onTouchEvent(MotionEvent ev) 
+    { 
+        //Log.e("CalcView", ev.toString());
+        boolean ret = true;
+        int act = ev.getAction();
+        mParams[1] = (int)ev.getX();
+        mParams[2] = (int)ev.getY();
+
+        if (act == ev.ACTION_DOWN) {
+            mParams[0] = 1;
+        } else if (act == ev.ACTION_UP) {
+            //mParams[0] = 0;
+            ret = false;
+        }
+        mIntAlloc.subData1D(2, 3, mParams);
+
+        return ret;
+    } 
+}
+
+
diff --git a/libs/rs/java/Fountain/src/com/android/fountain/RSSurfaceView.java b/libs/rs/java/Fountain/src/com/android/fountain/RSSurfaceView.java
new file mode 100644
index 0000000..d18270a
--- /dev/null
+++ b/libs/rs/java/Fountain/src/com/android/fountain/RSSurfaceView.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.calc;
+
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.concurrent.Semaphore;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Log;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+public class RSSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
+    private SurfaceHolder mSurfaceHolder;
+
+    /**
+     * Standard View constructor. In order to render something, you
+     * must call {@link #setRenderer} to register a renderer.
+     */
+    public RSSurfaceView(Context context) {
+        super(context);
+        init();
+        Log.v("***", "RSSurfaceView");
+    }
+
+    /**
+     * Standard View constructor. In order to render something, you
+     * must call {@link #setRenderer} to register a renderer.
+     */
+    public RSSurfaceView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        init();
+        Log.v("***", "RSSurfaceView");
+    }
+
+    private void init() {
+        // Install a SurfaceHolder.Callback so we get notified when the
+        // underlying surface is created and destroyed
+        SurfaceHolder holder = getHolder();
+        holder.addCallback(this);
+        holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
+    }
+
+    /**
+     * This method is part of the SurfaceHolder.Callback interface, and is
+     * not normally called or subclassed by clients of RSSurfaceView.
+     */
+    public void surfaceCreated(SurfaceHolder holder) {
+        Log.v("***", "surfaceCreated");
+        mSurfaceHolder = holder;
+        //mGLThread.surfaceCreated();
+    }
+
+    /**
+     * This method is part of the SurfaceHolder.Callback interface, and is
+     * not normally called or subclassed by clients of RSSurfaceView.
+     */
+    public void surfaceDestroyed(SurfaceHolder holder) {
+        // Surface will be destroyed when we return
+        Log.v("***", "surfaceDestroyed");
+        //mGLThread.surfaceDestroyed();
+    }
+
+    /**
+     * This method is part of the SurfaceHolder.Callback interface, and is
+     * not normally called or subclassed by clients of RSSurfaceView.
+     */
+    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+        Log.v("***", "surfaceChanged");
+
+        //mGLThread.onWindowResize(w, h);
+    }
+
+    /**
+     * Inform the view that the activity is paused. The owner of this view must
+     * call this method when the activity is paused. Calling this method will
+     * pause the rendering thread.
+     * Must not be called before a renderer has been set.
+     */
+    public void onPause() {
+        Log.v("***", "onPause");
+        //mGLThread.onPause();
+    }
+
+    /**
+     * Inform the view that the activity is resumed. The owner of this view must
+     * call this method when the activity is resumed. Calling this method will
+     * recreate the OpenGL display and resume the rendering
+     * thread.
+     * Must not be called before a renderer has been set.
+     */
+    public void onResume() {
+        Log.v("***", "onResume");
+        //mGLThread.onResume();
+    }
+
+    /**
+     * Queue a runnable to be run on the GL rendering thread. This can be used
+     * to communicate with the Renderer on the rendering thread.
+     * Must not be called before a renderer has been set.
+     * @param r the runnable to be run on the GL rendering thread.
+     */
+    public void queueEvent(Runnable r) {
+        Log.v("***", "queueEvent");
+        //mGLThread.queueEvent(r);
+    }
+
+    /**
+     * This method is used as part of the View class and is not normally
+     * called or subclassed by clients of RSSurfaceView.
+     * Must not be called before a renderer has been set.
+     */
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        //mGLThread.requestExitAndWait();
+    }
+
+    // ----------------------------------------------------------------------
+
+    public RenderScript createRenderScript() {
+        Log.v("***", "createRenderScript 1");
+        Surface sur = null;
+        while ((sur == null) || (mSurfaceHolder == null)) {
+            sur = getHolder().getSurface();
+        }
+        Log.v("***", "createRenderScript 2");
+        RenderScript rs = new RenderScript(sur);
+        Log.v("***", "createRenderScript 3 rs");
+        return rs;
+    }
+
+}
+
diff --git a/libs/rs/java/Fountain/src/com/android/fountain/RenderScript.java b/libs/rs/java/Fountain/src/com/android/fountain/RenderScript.java
new file mode 100644
index 0000000..bab9666
--- /dev/null
+++ b/libs/rs/java/Fountain/src/com/android/fountain/RenderScript.java
@@ -0,0 +1,717 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.calc;
+
+import android.os.Bundle;
+import android.util.Log;
+import android.util.Config;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.Window;
+import android.view.View;
+import android.view.Surface;
+
+public class RenderScript {
+    private static final String LOG_TAG = "libRS_jni";
+    private static final boolean DEBUG  = false;
+    private static final boolean LOG_ENABLED = DEBUG ? Config.LOGD : Config.LOGV;
+
+
+
+       /*
+     * We use a class initializer to allow the native code to cache some
+     * field offsets.
+     */
+    private static boolean sInitialized;
+    native private static void _nInit();
+
+    static {
+        sInitialized = false;
+        try {
+            System.loadLibrary("RS_jni");
+            Log.e(LOG_TAG, "*** Renderscript INIT");
+            _nInit();
+            Log.e(LOG_TAG, "*** Renderscript INIT 3");
+            sInitialized = true;
+        } catch (UnsatisfiedLinkError e) {
+            Log.d(LOG_TAG, "RenderScript JNI library not found!");
+        }
+    }
+
+    native private int  nDeviceCreate();
+    native private void nDeviceDestroy(int dev);
+    native private int  nContextCreate(int dev, Surface sur, int ver);
+    native private void nContextDestroy(int con);
+
+    //void rsContextBindSampler (uint32_t slot, RsSampler sampler);
+    //void rsContextBindRootScript (RsScript sampler);
+    native private void nContextBindRootScript(int script);
+    native private void nContextBindSampler(int sampler, int slot);
+    native private void nContextBindProgramFragmentStore(int pfs);
+    native private void nContextBindProgramFragment(int pf);
+
+    native private void nElementBegin();
+    native private void nElementAddPredefined(int predef);
+    native private void nElementAdd(int kind, int type, int norm, int bits);
+    native private int  nElementCreate();
+    native private int  nElementGetPredefined(int predef);
+    native private void nElementDestroy(int obj);
+
+    native private void nTypeBegin(int elementID);
+    native private void nTypeAdd(int dim, int val);
+    native private int  nTypeCreate();
+    native private void nTypeDestroy(int id);
+
+    native private int  nAllocationCreateTyped(int type);
+    native private int  nAllocationCreatePredefSized(int predef, int count);
+    native private int  nAllocationCreateSized(int elem, int count);
+    //native private int  nAllocationCreateFromBitmap(type.mID);
+    native private void nAllocationUploadToTexture(int alloc, int baseMioLevel);
+    native private void nAllocationDestroy(int alloc);
+    native private void nAllocationData(int id, int[] d);
+    native private void nAllocationData(int id, float[] d);
+    native private void nAllocationSubData1D(int id, int off, int count, int[] d);
+    native private void nAllocationSubData1D(int id, int off, int count, float[] d);
+    native private void nAllocationSubData2D(int id, int xoff, int yoff, int w, int h, int[] d);
+    native private void nAllocationSubData2D(int id, int xoff, int yoff, int w, int h, float[] d);
+
+    native private void nTriangleMeshDestroy(int id);
+    native private void nTriangleMeshBegin(int vertex, int index);
+    native private void nTriangleMeshAddVertex_XY (float x, float y);
+    native private void nTriangleMeshAddVertex_XYZ (float x, float y, float z);
+    native private void nTriangleMeshAddVertex_XY_ST (float x, float y, float s, float t);
+    native private void nTriangleMeshAddVertex_XYZ_ST (float x, float y, float z, float s, float t);
+    native private void nTriangleMeshAddTriangle(int i1, int i2, int i3);
+    native private int  nTriangleMeshCreate();
+
+    native private void nAdapter1DDestroy(int id);
+    native private void nAdapter1DBindAllocation(int ad, int alloc);
+    native private void nAdapter1DSetConstraint(int ad, int dim, int value);
+    native private void nAdapter1DData(int ad, int[] d);
+    native private void nAdapter1DSubData(int ad, int off, int count, int[] d);
+    native private void nAdapter1DData(int ad, float[] d);
+    native private void nAdapter1DSubData(int ad, int off, int count, float[] d);
+    native private int  nAdapter1DCreate();
+
+    native private void nScriptDestroy(int script);
+    native private void nScriptBindAllocation(int vtm, int alloc, int slot);
+    native private void nScriptCBegin();
+    native private void nScriptCSetClearColor(float r, float g, float b, float a);
+    native private void nScriptCSetClearDepth(float depth);
+    native private void nScriptCSetClearStencil(int stencil);
+    native private void nScriptCAddType(int type);
+    native private void nScriptCSetRoot(boolean isRoot);
+    native private void nScriptCSetScript(String s);
+    native private int  nScriptCCreate();
+
+
+    native private void nProgramFragmentStoreBegin(int in, int out);
+    native private void nProgramFragmentStoreDepthFunc(int func);
+    native private void nProgramFragmentStoreDepthMask(boolean enable);
+    native private void nProgramFragmentStoreColorMask(boolean r, boolean g, boolean b, boolean a);
+    native private void nProgramFragmentStoreBlendFunc(int src, int dst);
+    native private void nProgramFragmentStoreDither(boolean enable);
+    native private int  nProgramFragmentStoreCreate();
+
+    native private void nProgramFragmentBegin(int in, int out);
+    native private void nProgramFragmentBindTexture(int vpf, int slot, int a);
+    native private void nProgramFragmentBindSampler(int vpf, int slot, int s);
+    native private void nProgramFragmentSetType(int slot, int vt);
+    native private void nProgramFragmentSetEnvMode(int slot, int env);
+    native private void nProgramFragmentSetTexEnable(int slot, boolean enable);
+    native private int  nProgramFragmentCreate();
+
+
+    private int     mDev;
+    private int     mContext;
+    private Surface mSurface;
+
+
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    // 
+
+    RenderScript(Surface sur) {
+        mSurface = sur;
+        mDev = nDeviceCreate();
+        mContext = nContextCreate(mDev, mSurface, 0);
+    }
+
+    private class BaseObj {
+        BaseObj() {
+            mID = 0;
+        }
+
+        int mID;
+        protected void finalize() throws Throwable
+        {
+            if (mID != 0) {
+                Log.v(LOG_TAG, 
+                      "Element finalized without having released the RS reference.");
+            }
+            super.finalize();
+        }
+    }
+
+    
+    //////////////////////////////////////////////////////////////////////////////////
+    // Element
+
+    public enum ElementPredefined {
+        USER_U8 (0),
+        USER_I8 (1),
+        USER_U16 (2),
+        USER_I16 (3),
+        USER_U32 (4),
+        USER_I32 (5),
+        USER_FLOAT (6),
+
+        RGB_565 (7),
+        RGBA_5551 (8),
+        RGBA_4444 (9),
+        RGB_888 (10),
+        RGBA_8888 (11),
+
+        INDEX_16 (12),
+        INDEX_32 (13),
+        XY_F32 (14),
+        XYZ_F32 (15),
+        ST_XY_F32 (16),
+        ST_XYZ_F32 (17),
+        NORM_XYZ_F32 (18),
+        NORM_ST_XYZ_F32 (19);
+
+        int mID;
+        ElementPredefined(int id) {
+            mID = id;
+        }
+    }
+
+    public enum DataType {
+        FLOAT (0),
+        UNSIGNED (1),
+        SIGNED (2);
+
+        int mID;
+        DataType(int id) {
+            mID = id;
+        }
+    }
+
+    public enum DataKind {
+        USER (0),
+        RED (1),
+        GREEN (2),
+        BLUE (3),
+        ALPHA (4),
+        LUMINANCE (5),
+        INTENSITY (6),
+        X (7),
+        Y (8),
+        Z (9),
+        W (10),
+        S (11),
+        T (12),
+        Q (13),
+        R (14),
+        NX (15),
+        NY (16),
+        NZ (17),
+        INDEX (18);
+
+        int mID;
+        DataKind(int id) {
+            mID = id;
+        }
+    }
+
+    public enum DepthFunc {
+        ALWAYS (0),
+        LESS (1),
+        LEQUAL (2),
+        GREATER (3),
+        GEQUAL (4),
+        EQUAL (5),
+        NOTEQUAL (6);
+
+        int mID;
+        DepthFunc(int id) {
+            mID = id;
+        }
+    }
+
+    public enum BlendSrcFunc {
+        ZERO (0),
+        ONE (1),
+        DST_COLOR (2),
+        ONE_MINUS_DST_COLOR (3),
+        SRC_ALPHA (4),
+        ONE_MINUS_SRC_ALPHA (5),
+        DST_ALPHA (6),
+        ONE_MINUS_DST_ALPA (7),
+        SRC_ALPHA_SATURATE (8);
+
+        int mID;
+        BlendSrcFunc(int id) {
+            mID = id;
+        }
+    }
+
+    public enum BlendDstFunc {
+        ZERO (0),
+        ONE (1),
+        SRC_COLOR (2),
+        ONE_MINUS_SRC_COLOR (3),
+        SRC_ALPHA (4),
+        ONE_MINUS_SRC_ALPHA (5),
+        DST_ALPHA (6),
+        ONE_MINUS_DST_ALPA (7);
+
+        int mID;
+        BlendDstFunc(int id) {
+            mID = id;
+        }
+    }
+
+    public enum EnvMode {
+        REPLACE (0),
+        MODULATE (1),
+        DECAL (2);
+
+        int mID;
+        EnvMode(int id) {
+            mID = id;
+        }
+    }
+
+    public class Element extends BaseObj {
+        Element(int id) {
+            mID = id;
+        }
+
+        public void estroy() {
+            nElementDestroy(mID);
+            mID = 0;
+        }
+    }
+
+    public void elementBegin() {
+        nElementBegin();
+    }
+
+    public void elementAddPredefined(ElementPredefined e) {
+        nElementAddPredefined(e.mID);
+    }
+
+    public void elementAdd(DataType dt, DataKind dk, boolean isNormalized, int bits) {
+        int norm = 0;
+        if (isNormalized) {
+            norm = 1;
+        }
+        nElementAdd(dt.mID, dk.mID, norm, bits);
+    }
+
+    public Element elementCreate() {
+        int id = nElementCreate();
+        return new Element(id);
+    }
+
+    public Element elementGetPredefined(ElementPredefined predef) {
+        int id = nElementGetPredefined(predef.mID);
+        return new Element(id);
+    }
+
+
+    //////////////////////////////////////////////////////////////////////////////////
+    // Type
+
+    public enum Dimension {
+        X (0),
+        Y (1),
+        Z (2),
+        LOD (3),
+        FACE (4),
+        ARRAY_0 (100);
+
+        int mID;
+        Dimension(int id) {
+            mID = id;
+        }
+    }
+
+    public class Type extends BaseObj {
+        Type(int id) {
+            mID = id;
+        }
+
+        public void destroy() {
+            nTypeDestroy(mID);
+            mID = 0;
+        }
+    }
+
+    public void typeBegin(Element e) {
+        nTypeBegin(e.mID);
+    }
+
+    public void typeAdd(Dimension d, int value) {
+        nTypeAdd(d.mID, value);
+    }
+
+    public Type typeCreate() {
+        int id = nTypeCreate();
+        return new Type(id);
+    }
+
+
+    //////////////////////////////////////////////////////////////////////////////////
+    // Allocation
+
+    public class Allocation extends BaseObj {
+        Allocation(int id) {
+            mID = id;
+        }
+
+        public void uploadToTexture(int baseMipLevel) {
+            nAllocationUploadToTexture(mID, baseMipLevel);
+        }
+
+        public void destroy() {
+            nAllocationDestroy(mID);
+            mID = 0;
+        }
+
+        public void data(int[] d) {
+            nAllocationData(mID, d);
+        }
+
+        public void data(float[] d) {
+            nAllocationData(mID, d);
+        }
+
+        public void subData1D(int off, int count, int[] d) {
+            nAllocationSubData1D(mID, off, count, d);
+        }
+
+        public void subData1D(int off, int count, float[] d) {
+            nAllocationSubData1D(mID, off, count, d);
+        }
+
+        public void subData2D(int xoff, int yoff, int w, int h, int[] d) {
+            nAllocationSubData2D(mID, xoff, yoff, w, h, d);
+        }
+
+        public void subData2D(int xoff, int yoff, int w, int h, float[] d) {
+            nAllocationSubData2D(mID, xoff, yoff, w, h, d);
+        }
+    }
+
+    public Allocation allocationCreateTyped(Type type) {
+        int id = nAllocationCreateTyped(type.mID);
+        return new Allocation(id);
+    }
+
+    public Allocation allocationCreatePredefSized(ElementPredefined e, int count) {
+        int id = nAllocationCreatePredefSized(e.mID, count);
+        return new Allocation(id);
+    }
+
+    public Allocation allocationCreateSized(Element e, int count) {
+        int id = nAllocationCreateSized(e.mID, count);
+        return new Allocation(id);
+    }
+
+    //public Allocation allocationCreateFromBitmap(string file, boolean genMips) {
+        //int id = nAllocationCreateTyped(type.mID);
+        //return new Allocation(id);
+    //}
+
+    //////////////////////////////////////////////////////////////////////////////////
+    // Adapter1D
+
+    public class Adapter1D extends BaseObj {
+        Adapter1D(int id) {
+            mID = id;
+        }
+
+        public void destroy() {
+            nAdapter1DDestroy(mID);
+            mID = 0;
+        }
+
+        public void bindAllocation(Allocation a) {
+            nAdapter1DBindAllocation(mID, a.mID);
+        }
+
+        public void setConstraint(Dimension dim, int value) {
+            nAdapter1DSetConstraint(mID, dim.mID, value);
+        }
+
+        public void data(int[] d) {
+            nAdapter1DData(mID, d);
+        }
+
+        public void subData(int off, int count, int[] d) {
+            nAdapter1DSubData(mID, off, count, d);
+        }
+
+        public void data(float[] d) {
+            nAdapter1DData(mID, d);
+        }
+
+        public void subData(int off, int count, float[] d) {
+            nAdapter1DSubData(mID, off, count, d);
+        }
+    }
+
+    public Adapter1D adapter1DCreate() {
+        int id = nAdapter1DCreate();
+        return new Adapter1D(id);
+    }
+
+
+    //////////////////////////////////////////////////////////////////////////////////
+    // Triangle Mesh
+
+    public class TriangleMesh extends BaseObj {
+        TriangleMesh(int id) {
+            mID = id;
+        }
+
+        public void destroy() {
+            nTriangleMeshDestroy(mID);
+            mID = 0;
+        }
+    }
+
+    public void triangleMeshBegin(Element vertex, Element index) {
+        nTriangleMeshBegin(vertex.mID, index.mID);
+    }
+
+    public void triangleMeshAddVertex_XY(float x, float y) {
+        nTriangleMeshAddVertex_XY(x, y);
+    }
+
+    public void triangleMeshAddVertex_XYZ(float x, float y, float z) {
+        nTriangleMeshAddVertex_XYZ(x, y, z);
+    }
+
+    public void triangleMeshAddVertex_XY_ST(float x, float y, float s, float t) {
+        nTriangleMeshAddVertex_XY_ST(x, y, s, t);
+    }
+
+    public void triangleMeshAddVertex_XYZ_ST(float x, float y, float z, float s, float t) {
+        nTriangleMeshAddVertex_XYZ_ST(x, y, z, s, t);
+    }
+
+    public void triangleMeshAddTriangle(int i1, int i2, int i3) {
+        nTriangleMeshAddTriangle(i1, i2, i3);
+    }
+
+    public TriangleMesh triangleMeshCreate() {
+        int id = nTriangleMeshCreate();
+        return new TriangleMesh(id);
+    }
+
+    //////////////////////////////////////////////////////////////////////////////////
+    // Script
+
+    public class Script extends BaseObj {
+        Script(int id) {
+            mID = id;
+        }
+
+        public void destroy() {
+            nScriptDestroy(mID);
+            mID = 0;
+        }
+
+        public void bindAllocation(Allocation va, int slot) {
+            nScriptBindAllocation(mID, va.mID, slot);
+        }
+    }
+
+    public void scriptCBegin() {
+        nScriptCBegin();
+    }
+
+    public void scriptCSetClearColor(float r, float g, float b, float a) {
+        nScriptCSetClearColor(r, g, b, a);
+    }
+
+    public void scriptCSetClearDepth(float d) {
+        nScriptCSetClearDepth(d);
+    }
+
+    public void scriptCSetClearStencil(int stencil) {
+        nScriptCSetClearStencil(stencil);
+    }
+
+    public void scriptCAddType(Type t) {
+        nScriptCAddType(t.mID);
+    }
+
+    public void scriptCSetRoot(boolean r) {
+        nScriptCSetRoot(r);
+    }
+
+    public void scriptCSetScript(String s) {
+        nScriptCSetScript(s);
+    }
+
+    public Script scriptCCreate() {
+        int id = nScriptCCreate();
+        return new Script(id);
+    }
+
+    //////////////////////////////////////////////////////////////////////////////////
+    // ProgramFragmentStore
+
+    public class ProgramFragmentStore extends BaseObj {
+        ProgramFragmentStore(int id) {
+            mID = id;
+        }
+
+        public void destroy() {
+            nScriptDestroy(mID);
+            mID = 0;
+        }
+    }
+
+    public void programFragmentStoreBegin(Element in, Element out) {
+        int inID = 0;
+        int outID = 0;
+        if (in != null) {
+            inID = in.mID;
+        }
+        if (out != null) {
+            outID = out.mID;
+        }
+        nProgramFragmentStoreBegin(inID, outID);
+    }
+
+    public void programFragmentStoreDepthFunc(DepthFunc func) {
+        nProgramFragmentStoreDepthFunc(func.mID);
+    }
+
+    public void programFragmentStoreDepthMask(boolean enable) {
+        nProgramFragmentStoreDepthMask(enable);
+    }
+
+    public void programFragmentStoreColorMask(boolean r, boolean g, boolean b, boolean a) {
+        nProgramFragmentStoreColorMask(r,g,b,a);
+    }
+
+    public void programFragmentStoreBlendFunc(BlendSrcFunc src, BlendDstFunc dst) {
+        nProgramFragmentStoreBlendFunc(src.mID, dst.mID);
+    }
+
+    public void programFragmentStoreDitherEnable(boolean enable) {
+        nProgramFragmentStoreDither(enable);
+    }
+
+    public ProgramFragmentStore programFragmentStoreCreate() {
+        int id = nProgramFragmentStoreCreate();
+        return new ProgramFragmentStore(id);
+    }
+
+    //////////////////////////////////////////////////////////////////////////////////
+    // ProgramFragment
+
+    public class ProgramFragment extends BaseObj {
+        ProgramFragment(int id) {
+            mID = id;
+        }
+
+        public void destroy() {
+            nScriptDestroy(mID);
+            mID = 0;
+        }
+
+        public void bindTexture(Allocation va, int slot) {
+            nProgramFragmentBindTexture(mID, slot, va.mID);
+        }
+
+        //public void bindSampler(Sampler vs, int slot) {
+            //nProgramFragmentBindSampler(mID, slot, vs.mID);
+        //}
+    }
+
+    public void programFragmentBegin(Element in, Element out) {
+        int inID = 0;
+        int outID = 0;
+        if (in != null) {
+            inID = in.mID;
+        }
+        if (out != null) {
+            outID = out.mID;
+        }
+        nProgramFragmentBegin(inID, outID);
+    }
+
+    public void programFragmentSetType(int slot, Type t) {
+        nProgramFragmentSetType(slot, t.mID);
+    }
+
+    public void programFragmentSetType(int slot, EnvMode t) {
+        nProgramFragmentSetEnvMode(slot, t.mID);
+    }
+
+    public void programFragmentSetTexEnable(int slot, boolean enable) {
+        nProgramFragmentSetTexEnable(slot, enable);
+    }
+
+    public ProgramFragment programFragmentCreate() {
+        int id = nProgramFragmentCreate();
+        return new ProgramFragment(id);
+    }
+
+
+    ///////////////////////////////////////////////////////////////////////////////////
+    // Root state
+
+    public void contextBindRootScript(Script s) {
+        nContextBindRootScript(s.mID);
+    }
+
+    //public void contextBindSampler(Sampler s, int slot) {
+        //nContextBindSampler(s.mID);
+    //}
+
+    public void contextBindProgramFragmentStore(ProgramFragmentStore pfs) {
+        nContextBindProgramFragmentStore(pfs.mID);
+    }
+
+    public void contextBindProgramFragment(ProgramFragment pf) {
+        nContextBindProgramFragment(pf.mID);
+    }
+
+/*
+    RsAdapter2D rsAdapter2DCreate ();
+    void rsAdapter2DBindAllocation (RsAdapter2D adapt, RsAllocation alloc);
+    void rsAdapter2DDestroy (RsAdapter2D adapter);
+    void rsAdapter2DSetConstraint (RsAdapter2D adapter, RsDimension dim, uint32_t value);
+    void rsAdapter2DData (RsAdapter2D adapter, const void * data);
+    void rsAdapter2DSubData (RsAdapter2D adapter, uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, const void * data);
+    void rsSamplerBegin ();
+    void rsSamplerSet (RsSamplerParam p, RsSamplerValue value);
+    RsSampler rsSamplerCreate ();
+    void rsSamplerBind (RsSampler sampler, RsAllocation alloc);
+*/
+
+}
+
diff --git a/libs/rs/jni/RenderScript_jni.cpp b/libs/rs/jni/RenderScript_jni.cpp
new file mode 100644
index 0000000..5b226a5
--- /dev/null
+++ b/libs/rs/jni/RenderScript_jni.cpp
@@ -0,0 +1,897 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <math.h>
+
+#include <utils/misc.h>
+#include <utils/Log.h>
+
+#include <ui/EGLNativeWindowSurface.h>
+#include <ui/Surface.h>
+
+#include "jni.h"
+#include "JNIHelp.h"
+#include "android_runtime/AndroidRuntime.h"
+
+#include "../RenderScript.h"
+#include "../RenderScriptEnv.h"
+
+//#define LOG_API LOGE
+#define LOG_API(...)
+
+using namespace android;
+
+extern "C" void test_script(void *con, const rsc_FunctionTable *ft, uint32_t launchID);
+
+void test_script(void *con, const rsc_FunctionTable *ft, uint32_t launchID)
+{
+    int count = ft->loadEnvI32(con, 0, 1);
+    int touch = ft->loadEnvI32(con, 0, 2);
+    int x = ft->loadEnvI32(con, 0, 3);
+    int y = 480 - ft->loadEnvI32(con, 0, 4);
+
+    int rate = 4;
+    int maxLife = (count / rate) - 1;
+    int lifeShift = 0;
+    {
+        int life = maxLife;
+        while (life > 255) {
+            life >>= 1;
+            lifeShift ++;
+        }
+    }
+
+    if (touch) {
+        int newPart = ft->loadEnvI32(con, 2, 0);
+        for (int ct2=0; ct2<rate; ct2++) {
+            int dx = ft->rand(con, 0x10000) - 0x8000;
+            int dy = ft->rand(con, 0x10000) - 0x8000;
+
+            int idx = newPart * 5 + 1;
+            ft->storeEnvI32(con, 2, idx, dx);
+            ft->storeEnvI32(con, 2, idx + 1, dy);
+            ft->storeEnvI32(con, 2, idx + 2, maxLife);
+            ft->storeEnvI32(con, 2, idx + 3, x << 16);
+            ft->storeEnvI32(con, 2, idx + 4, y << 16);
+
+            newPart++;
+            if (newPart >= count) {
+                newPart = 0;
+            }
+        }
+        ft->storeEnvI32(con, 2, 0, newPart);
+    }
+
+    // Emulate intrinsic perf...
+    int32_t * partPtr = (int32_t *)ft->loadEnvVp(con, 2, 4);
+    int32_t * vertPtr = (int32_t *)ft->loadEnvVp(con, 1, 0);
+
+    int drawCount = 0;
+    for (int ct=0; ct < count; ct++) {
+        //int srcIdx = ct * 5 + 1;
+        //int dstIdx = ct * 3 * 3;
+
+        int dx = partPtr[0]; //ft->loadEnvI32(con, 2, srcIdx);
+        int dy = partPtr[1]; //ft->loadEnvI32(con, 2, srcIdx + 1);
+        int life = partPtr[2]; //ft->loadEnvI32(con, 2, srcIdx + 2);
+        int posx = partPtr[3]; //ft->loadEnvI32(con, 2, srcIdx + 3);
+        int posy = partPtr[4]; //ft->loadEnvI32(con, 2, srcIdx + 4);
+
+        if (life) {
+            if (posy > 0) {
+                uint32_t c = 0xffafcf | ((life >> lifeShift) << 24);
+
+                ((uint32_t *)vertPtr)[0] = c; //ft->storeEnvU32(con, 1, dstIdx, c);
+                vertPtr[1] = posx; //ft->storeEnvI32(con, 1, dstIdx + 1, posx);
+                vertPtr[2] = posy; //ft->storeEnvI32(con, 1, dstIdx + 2, posy);
+
+                ((uint32_t *)vertPtr)[3] = c; //ft->storeEnvU32(con, 1, dstIdx + 3, c);
+                vertPtr[4] = posx + 0x10000; //ft->storeEnvI32(con, 1, dstIdx + 4, posx + 0x10000);
+                vertPtr[5] = posy + dy * 4; //ft->storeEnvI32(con, 1, dstIdx + 5, posy);
+
+                ((uint32_t *)vertPtr)[6] = c; //ft->storeEnvU32(con, 1, dstIdx + 6, c);
+                vertPtr[7] = posx - 0x10000; //ft->storeEnvI32(con, 1, dstIdx + 7, posx + 0x0800);
+                vertPtr[8] = posy + dy * 4; //ft->storeEnvI32(con, 1, dstIdx + 8, posy + 0x10000);
+
+                vertPtr += 9;
+                drawCount ++;
+            } else {
+                if (dy < 0) {
+                    dy = (-dy) >> 1;
+                }
+            }
+
+            posx += dx;
+            posy += dy;
+            dy -= 0x400;
+            life --;
+
+            partPtr[0] = dx; //ft->storeEnvI32(con, 2, srcIdx, dx);
+            partPtr[1] = dy; //ft->storeEnvI32(con, 2, srcIdx + 1, dy);
+            partPtr[2] = life; //ft->storeEnvI32(con, 2, srcIdx + 2, life);
+            partPtr[3] = posx; //ft->storeEnvI32(con, 2, srcIdx + 3, posx);
+            partPtr[4] = posy; //ft->storeEnvI32(con, 2, srcIdx + 4, posy);
+        }
+
+        partPtr += 5;
+    }
+
+    ft->drawTriangleArray(con, (RsAllocation)ft->loadEnvI32(con, 0, 5), drawCount);
+}
+
+
+// ---------------------------------------------------------------------------
+
+static void doThrow(JNIEnv* env, const char* exc, const char* msg = NULL)
+{
+    jclass npeClazz = env->FindClass(exc);
+    env->ThrowNew(npeClazz, msg);
+}
+
+static jfieldID gContextId;
+
+static void _nInit(JNIEnv *_env, jclass _this)
+{
+    LOGE("_nInit");
+    gContextId             = _env->GetFieldID(_this, "mContext", "I");
+}
+
+
+// ---------------------------------------------------------------------------
+
+static jint
+nDeviceCreate(JNIEnv *_env, jobject _this)
+{
+    LOG_API("nDeviceCreate");
+    return (jint)rsDeviceCreate();
+}
+
+static void
+nDeviceDestroy(JNIEnv *_env, jobject _this, jint dev)
+{
+    LOG_API("nDeviceDestroy");
+    return rsDeviceDestroy((RsDevice)dev);
+}
+
+static jint
+nContextCreate(JNIEnv *_env, jobject _this, jint dev, jobject wnd, jint ver)
+{
+    LOG_API("nContextCreate");
+
+    if (wnd == NULL) {
+        not_valid_surface:
+        doThrow(_env, "java/lang/IllegalArgumentException",
+                "Make sure the SurfaceView or associated SurfaceHolder has a valid Surface");
+        return 0;
+    }
+    jclass surface_class = _env->FindClass("android/view/Surface");
+    jfieldID surfaceFieldID = _env->GetFieldID(surface_class, "mSurface", "I");
+    Surface * window = (Surface*)_env->GetIntField(wnd, surfaceFieldID);
+    if (window == NULL)
+        goto not_valid_surface;
+
+    LOGE("nContextCreate 5");
+    return (jint)rsContextCreate((RsDevice)dev, window, ver);
+}
+
+static void
+nContextDestroy(JNIEnv *_env, jobject _this, jint con)
+{
+    LOG_API("nContextDestroy, con(%p)", (RsContext)con);
+    return rsContextDestroy((RsContext)con);
+}
+
+
+static void
+nElementBegin(JNIEnv *_env, jobject _this)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nElementBegin, con(%p)", con);
+    rsElementBegin();
+}
+
+static void
+nElementAddPredefined(JNIEnv *_env, jobject _this, jint predef)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nElementAddPredefined, con(%p), predef(%i)", con, predef);
+    rsElementAddPredefined((RsElementPredefined)predef);
+}
+
+static void
+nElementAdd(JNIEnv *_env, jobject _this, jint kind, jint type, jint norm, jint bits)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nElementAdd, con(%p), kind(%i), type(%i), norm(%i), bits(%i)", con, kind, type, norm, bits);
+    rsElementAdd((RsDataKind)kind, (RsDataType)type, norm != 0, (size_t)bits);
+}
+
+static jint
+nElementCreate(JNIEnv *_env, jobject _this)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nElementCreate, con(%p)", con);
+    return (jint)rsElementCreate();
+}
+
+static jint
+nElementGetPredefined(JNIEnv *_env, jobject _this, jint predef)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nElementGetPredefined, con(%p) predef(%i)", con, predef);
+    return (jint)rsElementGetPredefined((RsElementPredefined)predef);
+}
+
+static void
+nElementDestroy(JNIEnv *_env, jobject _this, jint e)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nElementDestroy, con(%p) e(%p)", con, (RsElement)e);
+    rsElementDestroy((RsElement)e);
+}
+
+// -----------------------------------
+
+static void
+nTypeBegin(JNIEnv *_env, jobject _this, jint eID)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nTypeBegin, con(%p) e(%p)", con, (RsElement)eID);
+    rsTypeBegin((RsElement)eID);
+}
+
+static void
+nTypeAdd(JNIEnv *_env, jobject _this, jint dim, jint val)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nTypeAdd, con(%p) dim(%i), val(%i)", con, dim, val);
+    rsTypeAdd((RsDimension)dim, val);
+}
+
+static jint
+nTypeCreate(JNIEnv *_env, jobject _this)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nTypeCreate, con(%p)", con);
+    return (jint)rsTypeCreate();
+}
+
+static void
+nTypeDestroy(JNIEnv *_env, jobject _this, jint eID)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nTypeDestroy, con(%p), t(%p)", con, (RsType)eID);
+    rsTypeDestroy((RsType)eID);
+}
+
+// -----------------------------------
+
+static jint
+nAllocationCreateTyped(JNIEnv *_env, jobject _this, jint e)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nAllocationCreateTyped, con(%p), e(%p)", con, (RsElement)e);
+    return (jint) rsAllocationCreateTyped((RsElement)e);
+}
+
+static jint
+nAllocationCreatePredefSized(JNIEnv *_env, jobject _this, jint predef, jint count)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nAllocationCreatePredefSized, con(%p), predef(%i), count(%i)", con, predef, count);
+    return (jint) rsAllocationCreatePredefSized((RsElementPredefined)predef, count);
+}
+
+static jint
+nAllocationCreateSized(JNIEnv *_env, jobject _this, jint e, jint count)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nAllocationCreateSized, con(%p), e(%p), count(%i)", con, (RsElement)e, count);
+    return (jint) rsAllocationCreateSized((RsElement)e, count);
+}
+
+static void
+nAllocationUploadToTexture(JNIEnv *_env, jobject _this, jint a, jint mip)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nAllocationUploadToTexture, con(%p), a(%p), mip(%i)", con, (RsAllocation)a, mip);
+    rsAllocationUploadToTexture((RsAllocation)a, mip);
+}
+
+static void
+nAllocationDestroy(JNIEnv *_env, jobject _this, jint a)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nAllocationDestroy, con(%p), a(%p)", con, (RsAllocation)a);
+    rsAllocationDestroy((RsAllocation)a);
+}
+
+static void
+nAllocationData_i(JNIEnv *_env, jobject _this, jint alloc, jintArray data)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    jint len = _env->GetArrayLength(data);
+    LOG_API("nAllocationData_i, con(%p), alloc(%p), len(%i)", con, (RsAllocation)alloc, len);
+    jint *ptr = _env->GetIntArrayElements(data, NULL);
+    rsAllocationData((RsAllocation)alloc, ptr);
+    _env->ReleaseIntArrayElements(data, ptr, JNI_ABORT);
+}
+
+static void
+nAllocationData_f(JNIEnv *_env, jobject _this, jint alloc, jfloatArray data)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    jint len = _env->GetArrayLength(data);
+    LOG_API("nAllocationData_i, con(%p), alloc(%p), len(%i)", con, (RsAllocation)alloc, len);
+    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
+    rsAllocationData((RsAllocation)alloc, ptr);
+    _env->ReleaseFloatArrayElements(data, ptr, JNI_ABORT);
+}
+
+static void
+nAllocationSubData1D_i(JNIEnv *_env, jobject _this, jint alloc, jint offset, jint count, jintArray data)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    jint len = _env->GetArrayLength(data);
+    LOG_API("nAllocation1DSubData_i, con(%p), adapter(%p), offset(%i), count(%i), len(%i)", con, (RsAllocation)alloc, offset, count, len);
+    jint *ptr = _env->GetIntArrayElements(data, NULL);
+    rsAllocation1DSubData((RsAllocation)alloc, offset, count, ptr);
+    _env->ReleaseIntArrayElements(data, ptr, JNI_ABORT);
+}
+
+static void
+nAllocationSubData1D_f(JNIEnv *_env, jobject _this, jint alloc, jint offset, jint count, jfloatArray data)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    jint len = _env->GetArrayLength(data);
+    LOG_API("nAllocation1DSubData_f, con(%p), adapter(%p), offset(%i), count(%i), len(%i)", con, (RsAllocation)alloc, offset, count, len);
+    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
+    rsAllocation1DSubData((RsAllocation)alloc, offset, count, ptr);
+    _env->ReleaseFloatArrayElements(data, ptr, JNI_ABORT);
+}
+
+static void
+nAllocationSubData2D_i(JNIEnv *_env, jobject _this, jint alloc, jint xoff, jint yoff, jint w, jint h, jintArray data)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    jint len = _env->GetArrayLength(data);
+    LOG_API("nAllocation2DSubData_i, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i)", con, (RsAllocation)alloc, xoff, yoff, w, h, len);
+    jint *ptr = _env->GetIntArrayElements(data, NULL);
+    rsAllocation2DSubData((RsAllocation)alloc, xoff, yoff, w, h, ptr);
+    _env->ReleaseIntArrayElements(data, ptr, JNI_ABORT);
+}
+
+static void
+nAllocationSubData2D_f(JNIEnv *_env, jobject _this, jint alloc, jint xoff, jint yoff, jint w, jint h, jfloatArray data)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    jint len = _env->GetArrayLength(data);
+    LOG_API("nAllocation2DSubData_i, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i)", con, (RsAllocation)alloc, xoff, yoff, w, h, len);
+    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
+    rsAllocation2DSubData((RsAllocation)alloc, xoff, yoff, w, h, ptr);
+    _env->ReleaseFloatArrayElements(data, ptr, JNI_ABORT);
+}
+
+
+
+// -----------------------------------
+
+static void
+nTriangleMeshDestroy(JNIEnv *_env, jobject _this, jint tm)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nTriangleMeshDestroy, con(%p), tm(%p)", con, (RsAllocation)tm);
+    rsTriangleMeshDestroy((RsTriangleMesh)tm);
+}
+
+static void
+nTriangleMeshBegin(JNIEnv *_env, jobject _this, jint v, jint i)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nTriangleMeshBegin, con(%p), vertex(%p), index(%p)", con, (RsElement)v, (RsElement)i);
+    rsTriangleMeshBegin((RsElement)v, (RsElement)i);
+}
+
+static void
+nTriangleMeshAddVertex_XY(JNIEnv *_env, jobject _this, jfloat x, jfloat y)
+{
+    float v[] = {x, y};
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nTriangleMeshAddVertex_XY, con(%p), x(%f), y(%f)", con, x, y);
+    rsTriangleMeshAddVertex(v);
+}
+
+static void
+nTriangleMeshAddVertex_XYZ(JNIEnv *_env, jobject _this, jfloat x, jfloat y, jfloat z)
+{
+    float v[] = {x, y, z};
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nTriangleMeshAddVertex_XYZ, con(%p), x(%f), y(%f), z(%f)", con, x, y, z);
+    rsTriangleMeshAddVertex(v);
+}
+
+static void
+nTriangleMeshAddVertex_XY_ST(JNIEnv *_env, jobject _this, jfloat x, jfloat y, jfloat s, jfloat t)
+{
+    float v[] = {s, t, x, y};
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nTriangleMeshAddVertex_XY_ST, con(%p), x(%f), y(%f), s(%f), t(%f)", con, x, y, s, t);
+    rsTriangleMeshAddVertex(v);
+}
+
+static void
+nTriangleMeshAddVertex_XYZ_ST(JNIEnv *_env, jobject _this, jfloat x, jfloat y, jfloat z, jfloat s, jfloat t)
+{
+    float v[] = {s, t, x, y, z};
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nTriangleMeshAddVertex_XYZ_ST, con(%p), x(%f), y(%f), z(%f), s(%f), t(%f)", con, x, y, z, s, t);
+    rsTriangleMeshAddVertex(v);
+}
+
+static void
+nTriangleMeshAddTriangle(JNIEnv *_env, jobject _this, jint i1, jint i2, jint i3)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nTriangleMeshAddTriangle, con(%p), i1(%i), i2(%i), i3(%i)", con, i1, i2, i3);
+    rsTriangleMeshAddTriangle(i1, i2, i3);
+}
+
+static jint
+nTriangleMeshCreate(JNIEnv *_env, jobject _this)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nTriangleMeshCreate, con(%p)", con);
+    return (jint) rsTriangleMeshCreate();
+}
+
+// -----------------------------------
+
+static void
+nAdapter1DDestroy(JNIEnv *_env, jobject _this, jint adapter)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nAdapter1DDestroy, con(%p), adapter(%p)", con, (RsAdapter1D)adapter);
+    rsAdapter1DDestroy((RsAdapter1D)adapter);
+}
+
+static void
+nAdapter1DBindAllocation(JNIEnv *_env, jobject _this, jint adapter, jint alloc)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nAdapter1DBindAllocation, con(%p), adapter(%p), alloc(%p)", con, (RsAdapter1D)adapter, (RsAllocation)alloc);
+    rsAdapter1DBindAllocation((RsAdapter1D)adapter, (RsAllocation)alloc);
+}
+
+static void
+nAdapter1DSetConstraint(JNIEnv *_env, jobject _this, jint adapter, jint dim, jint value)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nAdapter1DSetConstraint, con(%p), adapter(%p), dim(%i), value(%i)", con, (RsAdapter1D)adapter, dim, value);
+    rsAdapter1DSetConstraint((RsAdapter1D)adapter, (RsDimension)dim, value);
+}
+
+static void
+nAdapter1DData_i(JNIEnv *_env, jobject _this, jint adapter, jintArray data)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    jint len = _env->GetArrayLength(data);
+    LOG_API("nAdapter1DData_i, con(%p), adapter(%p), len(%i)", con, (RsAdapter1D)adapter, len);
+    jint *ptr = _env->GetIntArrayElements(data, NULL);
+    rsAdapter1DData((RsAdapter1D)adapter, ptr);
+    _env->ReleaseIntArrayElements(data, ptr, 0/*JNI_ABORT*/);
+}
+
+static void
+nAdapter1DSubData_i(JNIEnv *_env, jobject _this, jint adapter, jint offset, jint count, jintArray data)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    jint len = _env->GetArrayLength(data);
+    LOG_API("nAdapter1DSubData_i, con(%p), adapter(%p), offset(%i), count(%i), len(%i)", con, (RsAdapter1D)adapter, offset, count, len);
+    jint *ptr = _env->GetIntArrayElements(data, NULL);
+    rsAdapter1DSubData((RsAdapter1D)adapter, offset, count, ptr);
+    _env->ReleaseIntArrayElements(data, ptr, 0/*JNI_ABORT*/);
+}
+
+static void
+nAdapter1DData_f(JNIEnv *_env, jobject _this, jint adapter, jfloatArray data)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    jint len = _env->GetArrayLength(data);
+    LOG_API("nAdapter1DData_f, con(%p), adapter(%p), len(%i)", con, (RsAdapter1D)adapter, len);
+    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
+    rsAdapter1DData((RsAdapter1D)adapter, ptr);
+    _env->ReleaseFloatArrayElements(data, ptr, 0/*JNI_ABORT*/);
+}
+
+static void
+nAdapter1DSubData_f(JNIEnv *_env, jobject _this, jint adapter, jint offset, jint count, jfloatArray data)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    jint len = _env->GetArrayLength(data);
+    LOG_API("nAdapter1DSubData_f, con(%p), adapter(%p), offset(%i), count(%i), len(%i)", con, (RsAdapter1D)adapter, offset, count, len);
+    jfloat *ptr = _env->GetFloatArrayElements(data, NULL);
+    rsAdapter1DSubData((RsAdapter1D)adapter, offset, count, ptr);
+    _env->ReleaseFloatArrayElements(data, ptr, 0/*JNI_ABORT*/);
+}
+
+static jint
+nAdapter1DCreate(JNIEnv *_env, jobject _this)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nAdapter1DCreate, con(%p)", con);
+    return (jint)rsAdapter1DCreate();
+}
+
+// -----------------------------------
+
+static void
+nScriptDestroy(JNIEnv *_env, jobject _this, jint script)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nScriptDestroy, con(%p), script(%p)", con, (RsScript)script);
+    rsScriptDestroy((RsScript)script);
+}
+
+static void
+nScriptBindAllocation(JNIEnv *_env, jobject _this, jint script, jint alloc, jint slot)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nScriptBindAllocation, con(%p), script(%p), alloc(%p), slot(%i)", con, (RsScript)script, (RsAllocation)alloc, slot);
+    rsScriptBindAllocation((RsScript)script, (RsAllocation)alloc, slot);
+}
+
+static void
+nScriptCBegin(JNIEnv *_env, jobject _this)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nScriptCBegin, con(%p)", con);
+    rsScriptCBegin();
+}
+
+static void
+nScriptCSetClearColor(JNIEnv *_env, jobject _this, jfloat r, jfloat g, jfloat b, jfloat a)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nScriptCSetClearColor, con(%p), r(%f), g(%f), b(%f), a(%f)", con, r, g, b, a);
+    rsScriptCSetClearColor(r, g, b, a);
+}
+
+static void
+nScriptCSetClearDepth(JNIEnv *_env, jobject _this, jfloat d)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nScriptCSetClearColor, con(%p), depth(%f)", con, d);
+    rsScriptCSetClearDepth(d);
+}
+
+static void
+nScriptCSetClearStencil(JNIEnv *_env, jobject _this, jint stencil)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nScriptCSetClearStencil, con(%p), stencil(%i)", con, stencil);
+    rsScriptCSetClearStencil(stencil);
+}
+
+static void
+nScriptCAddType(JNIEnv *_env, jobject _this, jint type)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nScriptCAddType, con(%p), type(%p)", con, (RsType)type);
+    rsScriptCAddType((RsType)type);
+}
+
+static void
+nScriptCSetRoot(JNIEnv *_env, jobject _this, jboolean isRoot)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nScriptCSetRoot, con(%p), isRoot(%i)", con, isRoot);
+    rsScriptCSetRoot(isRoot);
+}
+
+static void
+nScriptCSetScript(JNIEnv *_env, jobject _this, jboolean isRoot)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("!!! nScriptCSetScript, con(%p)", con);
+    //nScriptCSetScript(isRoot);
+    rsScriptCSetScript((void *)test_script);
+}
+
+static jint
+nScriptCCreate(JNIEnv *_env, jobject _this)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nScriptCCreate, con(%p)", con);
+    return (jint)rsScriptCCreate();
+}
+
+// ---------------------------------------------------------------------------
+
+static void
+nProgramFragmentStoreBegin(JNIEnv *_env, jobject _this, jint in, jint out)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nProgramFragmentStoreBegin, con(%p), in(%p), out(%p)", con, (RsElement)in, (RsElement)out);
+    rsProgramFragmentStoreBegin((RsElement)in, (RsElement)out);
+}
+
+static void
+nProgramFragmentStoreDepthFunc(JNIEnv *_env, jobject _this, jint func)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nProgramFragmentStoreDepthFunc, con(%p), func(%i)", con, func);
+    rsProgramFragmentStoreDepthFunc((RsDepthFunc)func);
+}
+
+static void
+nProgramFragmentStoreDepthMask(JNIEnv *_env, jobject _this, jboolean enable)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nProgramFragmentStoreDepthMask, con(%p), enable(%i)", con, enable);
+    rsProgramFragmentStoreDepthMask(enable);
+}
+
+static void
+nProgramFragmentStoreColorMask(JNIEnv *_env, jobject _this, jboolean r, jboolean g, jboolean b, jboolean a)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nProgramFragmentStoreColorMask, con(%p), r(%i), g(%i), b(%i), a(%i)", con, r, g, b, a);
+    rsProgramFragmentStoreColorMask(r, g, b, a);
+}
+
+static void
+nProgramFragmentStoreBlendFunc(JNIEnv *_env, jobject _this, int src, int dst)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nProgramFragmentStoreBlendFunc, con(%p), src(%i), dst(%i)", con, src, dst);
+    rsProgramFragmentStoreBlendFunc((RsBlendSrcFunc)src, (RsBlendDstFunc)dst);
+}
+
+static void
+nProgramFragmentStoreDither(JNIEnv *_env, jobject _this, jboolean enable)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nProgramFragmentStoreDither, con(%p), enable(%i)", con, enable);
+    rsProgramFragmentStoreDither(enable);
+}
+
+static jint
+nProgramFragmentStoreCreate(JNIEnv *_env, jobject _this)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nProgramFragmentStoreCreate, con(%p)", con);
+    return (jint)rsProgramFragmentStoreCreate();
+}
+
+// ---------------------------------------------------------------------------
+
+static void
+nProgramFragmentBegin(JNIEnv *_env, jobject _this, jint in, jint out)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nProgramFragmentBegin, con(%p), in(%p), out(%p)", con, (RsElement)in, (RsElement)out);
+    rsProgramFragmentBegin((RsElement)in, (RsElement)out);
+}
+
+static void
+nProgramFragmentBindTexture(JNIEnv *_env, jobject _this, jint vpf, jint slot, jint a)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nProgramFragmentBindTexture, con(%p), vpf(%p), slot(%i), a(%p)", con, (RsProgramFragment)vpf, slot, (RsAllocation)a);
+    rsProgramFragmentBindTexture((RsProgramFragment)vpf, slot, (RsAllocation)a);
+}
+
+static void
+nProgramFragmentBindSampler(JNIEnv *_env, jobject _this, jint vpf, jint slot, jint a)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nProgramFragmentBindSampler, con(%p), vpf(%p), slot(%i), a(%p)", con, (RsProgramFragment)vpf, slot, (RsSampler)a);
+    rsProgramFragmentBindSampler((RsProgramFragment)vpf, slot, (RsSampler)a);
+}
+
+static void
+nProgramFragmentSetType(JNIEnv *_env, jobject _this, jint slot, jint vt)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nProgramFragmentSetType, con(%p), slot(%i), vt(%p)", con, slot, (RsType)vt);
+    rsProgramFragmentSetType(slot, (RsType)vt);
+}
+
+static void
+nProgramFragmentSetEnvMode(JNIEnv *_env, jobject _this, jint slot, jint env)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nProgramFragmentSetEnvMode, con(%p), slot(%i), vt(%i)", con, slot, env);
+    rsProgramFragmentSetEnvMode(slot, (RsTexEnvMode)env);
+}
+
+static void
+nProgramFragmentSetTexEnable(JNIEnv *_env, jobject _this, jint slot, jboolean enable)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nProgramFragmentSetTexEnable, con(%p), slot(%i), enable(%i)", con, slot, enable);
+    rsProgramFragmentSetTexEnable(slot, enable);
+}
+
+static jint
+nProgramFragmentCreate(JNIEnv *_env, jobject _this, jint slot, jboolean enable)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nProgramFragmentCreate, con(%p)", con);
+    return (jint)rsProgramFragmentCreate();
+}
+
+
+// ---------------------------------------------------------------------------
+
+static void
+nContextBindRootScript(JNIEnv *_env, jobject _this, jint script)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nContextBindRootScript, con(%p), script(%p)", con, (RsScript)script);
+    rsContextBindRootScript((RsScript)script);
+}
+
+static void
+nContextBindSampler(JNIEnv *_env, jobject _this, jint sampler, jint slot)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nContextBindSampler, con(%p), sampler(%p), slot(%i)", con, (RsSampler)sampler, slot);
+    rsContextBindSampler(slot, (RsSampler)sampler);
+}
+
+static void
+nContextBindProgramFragmentStore(JNIEnv *_env, jobject _this, jint pfs)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nContextBindProgramFragmentStore, con(%p), pfs(%p)", con, (RsProgramFragmentStore)pfs);
+    rsContextBindProgramFragmentStore((RsProgramFragmentStore)pfs);
+}
+
+static void
+nContextBindProgramFragment(JNIEnv *_env, jobject _this, jint pf)
+{
+    RsContext con = (RsContext)(_env->GetIntField(_this, gContextId));
+    LOG_API("nContextBindProgramFragment, con(%p), pf(%p)", con, (RsProgramFragment)pf);
+    rsContextBindProgramFragment((RsProgramFragment)pf);
+}
+
+
+// ---------------------------------------------------------------------------
+
+
+static const char *classPathName = "com/android/calc/RenderScript";
+
+static JNINativeMethod methods[] = {
+{"_nInit",                         "()V",                                  (void*)_nInit },
+{"nDeviceCreate",                  "()I",                                  (void*)nDeviceCreate },
+{"nDeviceDestroy",                 "(I)V",                                 (void*)nDeviceDestroy },
+{"nContextCreate",                 "(ILandroid/view/Surface;I)I",          (void*)nContextCreate },
+{"nContextDestroy",                "(I)V",                                 (void*)nContextDestroy },
+
+{"nElementBegin",                  "()V",                                  (void*)nElementBegin },
+{"nElementAddPredefined",          "(I)V",                                 (void*)nElementAddPredefined },
+{"nElementAdd",                    "(IIII)V",                              (void*)nElementAdd },
+{"nElementCreate",                 "()I",                                  (void*)nElementCreate },
+{"nElementGetPredefined",          "(I)I",                                 (void*)nElementGetPredefined },
+{"nElementDestroy",                "(I)V",                                 (void*)nElementDestroy },
+
+{"nTypeBegin",                     "(I)V",                                 (void*)nTypeBegin },
+{"nTypeAdd",                       "(II)V",                                (void*)nTypeAdd },
+{"nTypeCreate",                    "()I",                                  (void*)nTypeCreate },
+{"nTypeDestroy",                   "(I)V",                                 (void*)nTypeDestroy },
+
+{"nAllocationCreateTyped",         "(I)I",                                 (void*)nAllocationCreateTyped },
+{"nAllocationCreatePredefSized",   "(II)I",                                (void*)nAllocationCreatePredefSized },
+{"nAllocationCreateSized",         "(II)I",                                (void*)nAllocationCreateSized },
+//{"nAllocationCreateFromBitmap",    "(I)V",                                 (void*)nAllocationCreateFromBitmap },
+{"nAllocationUploadToTexture",     "(II)V",                                (void*)nAllocationUploadToTexture },
+{"nAllocationDestroy",             "(I)V",                                 (void*)nAllocationDestroy },
+{"nAllocationData",                "(I[I)V",                               (void*)nAllocationData_i },
+{"nAllocationData",                "(I[F)V",                               (void*)nAllocationData_f },
+{"nAllocationSubData1D",           "(III[I)V",                             (void*)nAllocationSubData1D_i },
+{"nAllocationSubData1D",           "(III[F)V",                             (void*)nAllocationSubData1D_f },
+{"nAllocationSubData2D",           "(IIIII[I)V",                           (void*)nAllocationSubData2D_i },
+{"nAllocationSubData2D",           "(IIIII[F)V",                           (void*)nAllocationSubData2D_f },
+
+{"nTriangleMeshDestroy",           "(I)V",                                 (void*)nTriangleMeshDestroy },
+{"nTriangleMeshBegin",             "(II)V",                                (void*)nTriangleMeshBegin },
+{"nTriangleMeshAddVertex_XY",      "(FF)V",                                (void*)nTriangleMeshAddVertex_XY },
+{"nTriangleMeshAddVertex_XYZ",     "(FFF)V",                               (void*)nTriangleMeshAddVertex_XYZ },
+{"nTriangleMeshAddVertex_XY_ST",   "(FFFF)V",                              (void*)nTriangleMeshAddVertex_XY_ST },
+{"nTriangleMeshAddVertex_XYZ_ST",  "(FFFFF)V",                             (void*)nTriangleMeshAddVertex_XYZ_ST },
+{"nTriangleMeshAddTriangle",       "(III)V",                               (void*)nTriangleMeshAddTriangle },
+{"nTriangleMeshCreate",            "()I",                                  (void*)nTriangleMeshCreate },
+
+{"nAdapter1DDestroy",              "(I)V",                                 (void*)nAdapter1DDestroy },
+{"nAdapter1DBindAllocation",       "(II)V",                                (void*)nAdapter1DBindAllocation },
+{"nAdapter1DSetConstraint",        "(III)V",                               (void*)nAdapter1DSetConstraint },
+{"nAdapter1DData",                 "(I[I)V",                               (void*)nAdapter1DData_i },
+{"nAdapter1DSubData",              "(III[I)V",                             (void*)nAdapter1DSubData_i },
+{"nAdapter1DData",                 "(I[F)V",                               (void*)nAdapter1DData_f },
+{"nAdapter1DSubData",              "(III[F)V",                             (void*)nAdapter1DSubData_f },
+{"nAdapter1DCreate",               "()I",                                  (void*)nAdapter1DCreate },
+
+{"nScriptDestroy",                 "(I)V",                                 (void*)nScriptDestroy },
+{"nScriptBindAllocation",          "(III)V",                               (void*)nScriptBindAllocation },
+{"nScriptCBegin",                  "()V",                                  (void*)nScriptCBegin },
+{"nScriptCSetClearColor",          "(FFFF)V",                              (void*)nScriptCSetClearColor },
+{"nScriptCSetClearDepth",          "(F)V",                                 (void*)nScriptCSetClearDepth },
+{"nScriptCSetClearStencil",        "(I)V",                                 (void*)nScriptCSetClearStencil },
+{"nScriptCAddType",                "(I)V",                                 (void*)nScriptCAddType },
+{"nScriptCSetRoot",                "(Z)V",                                 (void*)nScriptCSetRoot },
+{"nScriptCSetScript",              "(Ljava/lang/String;)V",                (void*)nScriptCSetScript },
+{"nScriptCCreate",                 "()I",                                  (void*)nScriptCCreate },
+
+{"nProgramFragmentStoreBegin",     "(II)V",                                (void*)nProgramFragmentStoreBegin },
+{"nProgramFragmentStoreDepthFunc", "(I)V",                                 (void*)nProgramFragmentStoreDepthFunc },
+{"nProgramFragmentStoreDepthMask", "(Z)V",                                 (void*)nProgramFragmentStoreDepthMask },
+{"nProgramFragmentStoreColorMask", "(ZZZZ)V",                              (void*)nProgramFragmentStoreColorMask },
+{"nProgramFragmentStoreBlendFunc", "(II)V",                                (void*)nProgramFragmentStoreBlendFunc },
+{"nProgramFragmentStoreDither",    "(Z)V",                                 (void*)nProgramFragmentStoreDither },
+{"nProgramFragmentStoreCreate",    "()I",                                  (void*)nProgramFragmentStoreCreate },
+
+{"nProgramFragmentBegin",          "(II)V",                                (void*)nProgramFragmentBegin },
+{"nProgramFragmentBindTexture",    "(III)V",                               (void*)nProgramFragmentBindTexture },
+{"nProgramFragmentBindSampler",    "(III)V",                               (void*)nProgramFragmentBindSampler },
+{"nProgramFragmentSetType",        "(II)V",                                (void*)nProgramFragmentSetType },
+{"nProgramFragmentSetEnvMode",     "(II)V",                                (void*)nProgramFragmentSetEnvMode },
+{"nProgramFragmentSetTexEnable",   "(IZ)V",                                (void*)nProgramFragmentSetTexEnable },
+{"nProgramFragmentCreate",         "()I",                                  (void*)nProgramFragmentCreate },
+
+{"nContextBindRootScript",         "(I)V",                                 (void*)nContextBindRootScript },
+//{"nContextBindSampler",          "(II)V",                                (void*)nContextBindSampler },
+{"nContextBindProgramFragmentStore","(I)V",                                (void*)nContextBindProgramFragmentStore },
+{"nContextBindProgramFragment",    "(I)V",                                 (void*)nContextBindProgramFragment },
+
+};
+
+static int registerFuncs(JNIEnv *_env)
+{
+    return android::AndroidRuntime::registerNativeMethods(
+            _env, classPathName, methods, NELEM(methods));
+}
+
+// ---------------------------------------------------------------------------
+
+jint JNI_OnLoad(JavaVM* vm, void* reserved)
+{
+    JNIEnv* env = NULL;
+    jint result = -1;
+
+    LOGE("****************************************************\n");
+
+    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
+        LOGE("ERROR: GetEnv failed\n");
+        goto bail;
+    }
+    assert(env != NULL);
+
+    if (registerFuncs(env) < 0) {
+        LOGE("ERROR: MediaPlayer native registration failed\n");
+        goto bail;
+    }
+
+    /* success -- return valid version number */
+    result = JNI_VERSION_1_4;
+
+bail:
+    return result;
+}
diff --git a/libs/rs/rs.spec b/libs/rs/rs.spec
new file mode 100644
index 0000000..6168bd7
--- /dev/null
+++ b/libs/rs/rs.spec
@@ -0,0 +1,392 @@
+
+
+ContextBindSampler {
+	param uint32_t slot
+	param RsSampler sampler
+	}
+
+ContextBindRootScript {
+	param RsScript sampler
+	}
+
+ContextBindProgramFragmentStore {
+	param RsProgramFragmentStore pgm
+	}
+
+ContextBindProgramFragment {
+	param RsProgramFragment pgm
+	}
+
+ContextBindProgramVertex {
+	param RsProgramVertex pgm
+	}
+
+
+ElementBegin {
+}
+
+ElementAddPredefined {
+	param RsElementPredefined predef
+	}
+
+ElementAdd {
+	param RsDataKind dataKind
+	param RsDataType dataType
+	param bool isNormalized
+	param size_t bits
+	}
+
+ElementCreate {
+	ret RsElement
+	}
+
+ElementGetPredefined {
+	param RsElementPredefined predef
+	ret RsElement
+	}
+
+ElementDestroy {
+	param RsElement ve
+	}
+
+TypeBegin {
+	param RsElement type
+	}
+
+TypeAdd {
+	param RsDimension dim
+	param size_t value
+	}
+
+TypeCreate {
+	ret RsType
+	}
+
+TypeDestroy {
+	param RsType p
+	}
+
+AllocationCreateTyped {
+	param RsType type
+	ret RsAllocation
+	}
+
+AllocationCreatePredefSized {
+	param RsElementPredefined predef
+	param size_t count
+	ret RsAllocation
+	}
+
+AllocationCreateSized {
+	param RsElement e
+	param size_t count
+	ret RsAllocation
+	}
+
+AllocationCreateFromBitmap {
+	param const char *file
+	param bool genMips
+	ret RsAllocation
+	}
+
+AllocationUploadToTexture {
+	param RsAllocation alloc
+	param uint32_t baseMipLevel
+	}
+
+AllocationUploadToBufferObject {
+	param RsAllocation alloc
+	}
+
+AllocationDestroy {
+	param RsAllocation alloc
+	}
+
+
+AllocationData {
+	param RsAllocation va
+	param const void * data
+	} 
+
+Allocation1DSubData {
+	param RsAllocation va
+	param uint32_t xoff
+	param uint32_t count
+	param const void *data
+	} 
+
+Allocation2DSubData {
+	param RsAllocation va
+	param uint32_t xoff
+	param uint32_t yoff
+	param uint32_t w
+	param uint32_t h
+	param const void *data
+	}
+
+
+Adapter1DCreate {
+	ret RsAdapter1D
+	}
+
+Adapter1DBindAllocation {
+	param RsAdapter1D adapt
+	param RsAllocation alloc
+	}
+
+Adapter1DDestroy {
+	param RsAdapter1D adapter
+	}
+
+Adapter1DSetConstraint {
+	param RsAdapter1D adapter
+	param RsDimension dim
+	param uint32_t value
+	}
+
+Adapter1DData {
+	param RsAdapter1D adapter
+	param const void * data
+	} 
+
+Adapter1DSubData {
+	param RsAdapter1D adapter
+	param uint32_t xoff
+	param uint32_t count
+	param const void *data
+	} 
+
+Adapter2DCreate {
+	ret RsAdapter2D
+	}
+
+Adapter2DBindAllocation {
+	param RsAdapter2D adapt
+	param RsAllocation alloc
+	}
+
+Adapter2DDestroy {
+	param RsAdapter2D adapter
+	}
+
+Adapter2DSetConstraint {
+	param RsAdapter2D adapter
+	param RsDimension dim
+	param uint32_t value
+	}
+
+Adapter2DData {
+	param RsAdapter2D adapter
+	param const void *data
+	} 
+
+Adapter2DSubData {
+	param RsAdapter2D adapter
+	param uint32_t xoff
+	param uint32_t yoff
+	param uint32_t w
+	param uint32_t h
+	param const void *data
+	}
+
+SamplerBegin {
+	}
+
+SamplerSet {
+	param RsSamplerParam p
+	param RsSamplerValue value
+	}
+
+SamplerCreate {
+	ret RsSampler
+	}
+
+
+TriangleMeshBegin {
+	param RsElement vertex
+	param RsElement index
+	}
+
+TriangleMeshAddVertex {
+	param const void *vtx
+	}
+
+TriangleMeshAddTriangle {
+	param uint32_t idx1
+	param uint32_t idx2
+	param uint32_t idx3
+	}
+
+TriangleMeshCreate {
+	ret RsTriangleMesh
+	}
+
+TriangleMeshDestroy {
+	param RsTriangleMesh mesh
+	}
+
+TriangleMeshRender {
+	param RsTriangleMesh vtm
+	}
+
+TriangleMeshRenderRange {
+	param RsTriangleMesh vtm
+	param uint32_t start
+	param uint32_t count
+	}
+
+ScriptDestroy {
+	param RsScript script
+	}
+
+ScriptBindAllocation {
+	param RsScript vtm
+	param RsAllocation va
+	param uint32_t slot
+	}
+
+
+ScriptCBegin {
+	}
+
+ScriptCSetClearColor {
+	param float r
+	param float g
+	param float b
+	param float a
+	}
+
+ScriptCSetClearDepth {
+	param float depth
+	}
+
+ScriptCSetClearStencil {
+	param uint32_t stencil
+	}
+
+ScriptCAddType {
+	param RsType type
+	}
+
+ScriptCSetRoot {
+	param bool isRoot
+	}
+
+ScriptCSetOrtho {
+	param bool isOrtho
+	}
+
+ScriptCSetScript {
+	param void * ptr
+	}
+
+ScriptCCreate {
+	ret RsScript
+	}
+
+
+ProgramFragmentStoreBegin {
+	param RsElement in
+	param RsElement out
+	}
+
+ProgramFragmentStoreColorMask {
+	param bool r
+	param bool g
+	param bool b
+	param bool a
+	}
+
+ProgramFragmentStoreBlendFunc {
+	param RsBlendSrcFunc srcFunc
+	param RsBlendDstFunc destFunc
+	}
+
+ProgramFragmentStoreDepthMask {
+	param bool enable
+}
+
+ProgramFragmentStoreDither {
+	param bool enable
+}
+
+ProgramFragmentStoreDepthFunc {
+	param RsDepthFunc func
+}
+
+ProgramFragmentStoreCreate {
+	ret RsProgramFragmentStore
+	}
+
+
+
+ProgramFragmentBegin {
+	param RsElement in
+	param RsElement out
+	}
+
+ProgramFragmentBindTexture {
+	param RsProgramFragment pf
+	param uint32_t slot
+	param RsAllocation a
+	}
+
+ProgramFragmentBindSampler {
+	param RsProgramFragment pf
+	param uint32_t slot
+	param RsSampler s
+	}
+
+ProgramFragmentSetType {
+	param uint32_t slot
+	param RsType t
+	}
+
+ProgramFragmentSetEnvMode {
+	param uint32_t slot
+	param RsTexEnvMode env
+	}
+
+ProgramFragmentSetTexEnable {
+	param uint32_t slot
+	param bool enable
+	}
+
+ProgramFragmentCreate {
+	ret RsProgramFragment
+	}
+
+
+
+ProgramVertexBegin {
+	param RsElement in
+	param RsElement out
+	}
+
+ProgramVertexCreate {
+	ret RsProgramVertex
+	}
+
+ProgramVertexBindAllocation {
+	param RsProgramVertex vpgm
+	param uint32_t slot
+	param RsAllocation constants
+	}
+
+ProgramVertexSetType {
+	param uint32_t slot
+	param RsType constants
+	}
+
+ProgramVertexSetCameraMode {
+	param bool ortho
+	}
+
+ProgramVertexSetTextureMatrixEnable {
+	param bool enable
+	}
+
+ProgramVertexSetModelMatrixEnable {
+	param bool enable
+	}
+
diff --git a/libs/rs/rsAdapter.cpp b/libs/rs/rsAdapter.cpp
new file mode 100644
index 0000000..7ac2aed
--- /dev/null
+++ b/libs/rs/rsAdapter.cpp
@@ -0,0 +1,245 @@
+
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsContext.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+
+Adapter1D::Adapter1D()
+{
+    reset();
+}
+
+Adapter1D::Adapter1D(Allocation *a)
+{
+    reset();
+    setAllocation(a);
+}
+
+void Adapter1D::reset()
+{
+    mY = 0;
+    mZ = 0;
+    mLOD = 0;
+    mFace = 0;
+}
+
+void * Adapter1D::getElement(uint32_t x)
+{
+    rsAssert(mAllocation.get());
+    rsAssert(mAllocation->getPtr());
+    rsAssert(mAllocation->getType());
+    uint8_t * ptr = static_cast<uint8_t *>(mAllocation->getPtr());
+    ptr += mAllocation->getType()->getLODOffset(mLOD, x, mY);
+    return ptr;
+}
+
+void Adapter1D::subData(uint32_t xoff, uint32_t count, const void *data)
+{
+    if (mAllocation.get() && mAllocation.get()->getType()) {
+        void *ptr = getElement(xoff);
+        count *= mAllocation.get()->getType()->getElementSizeBytes();
+        memcpy(ptr, data, count);
+    }
+}
+
+void Adapter1D::data(const void *data)
+{
+    memcpy(getElement(0), 
+           data, 
+           mAllocation.get()->getType()->getSizeBytes());
+}
+
+namespace android {
+namespace renderscript {
+
+RsAdapter1D rsi_Adapter1DCreate(Context *rsc)
+{
+    return new Adapter1D();
+}
+
+void rsi_Adapter1DDestroy(Context *rsc, RsAdapter1D va)
+{
+    Adapter1D * a = static_cast<Adapter1D *>(va);
+    a->decRef();
+}
+
+void rsi_Adapter1DBindAllocation(Context *rsc, RsAdapter1D va, RsAllocation valloc)
+{
+    Adapter1D * a = static_cast<Adapter1D *>(va);
+    Allocation * alloc = static_cast<Allocation *>(valloc);
+    a->setAllocation(alloc);
+}
+
+void rsi_Adapter1DSetConstraint(Context *rsc, RsAdapter1D va, RsDimension dim, uint32_t value)
+{
+    Adapter1D * a = static_cast<Adapter1D *>(va);
+    switch(dim) {
+    case RS_DIMENSION_X:
+        rsAssert(!"Cannot contrain X in an 1D adapter");
+        return;
+    case RS_DIMENSION_Y:
+        a->setY(value);
+        break;
+    case RS_DIMENSION_Z:
+        a->setZ(value);
+        break;
+    case RS_DIMENSION_LOD:
+        a->setLOD(value);
+        break;
+    case RS_DIMENSION_FACE:
+        a->setFace(value);
+        break;
+    default:
+        rsAssert(!"Unimplemented constraint");
+        return;
+    }
+}
+
+void rsi_Adapter1DSubData(Context *rsc, RsAdapter1D va, uint32_t xoff, uint32_t count, const void *data)
+{
+    Adapter1D * a = static_cast<Adapter1D *>(va);
+    a->subData(xoff, count, data);
+}
+
+void rsi_Adapter1DData(Context *rsc, RsAdapter1D va, const void *data)
+{
+    Adapter1D * a = static_cast<Adapter1D *>(va);
+    a->data(data);
+}
+
+}
+}
+
+//////////////////////////
+
+Adapter2D::Adapter2D()
+{
+    reset();
+}
+
+Adapter2D::Adapter2D(Allocation *a)
+{
+    reset();
+    setAllocation(a);
+}
+
+void Adapter2D::reset()
+{
+    mZ = 0;
+    mLOD = 0;
+    mFace = 0;
+}
+
+void * Adapter2D::getElement(uint32_t x, uint32_t y) const
+{
+    rsAssert(mAllocation.get());
+    rsAssert(mAllocation->getPtr());
+    rsAssert(mAllocation->getType());
+    uint8_t * ptr = static_cast<uint8_t *>(mAllocation->getPtr());
+    ptr += mAllocation->getType()->getLODOffset(mLOD, x, y);
+    return ptr;
+}
+
+void Adapter2D::subData(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, const void *data)
+{
+    rsAssert(mAllocation.get());
+    rsAssert(mAllocation->getPtr());
+    rsAssert(mAllocation->getType());
+
+    uint32_t eSize = mAllocation.get()->getType()->getElementSizeBytes();
+    uint32_t lineSize = eSize * w;
+    uint32_t destW = getDimX();
+
+    const uint8_t *src = static_cast<const uint8_t *>(data);
+    for (uint32_t line=yoff; line < (yoff+h); line++) {
+        memcpy(getElement(xoff, line), src, lineSize);
+        src += lineSize;
+    }
+}
+
+void Adapter2D::data(const void *data)
+{
+    memcpy(getElement(0,0), 
+           data, 
+           mAllocation.get()->getType()->getSizeBytes());
+}
+
+
+
+namespace android {
+namespace renderscript {
+
+RsAdapter2D rsi_Adapter2DCreate(Context *rsc)
+{
+    return new Adapter2D();
+}
+
+void rsi_Adapter2DDestroy(Context *rsc, RsAdapter2D va)
+{
+    Adapter2D * a = static_cast<Adapter2D *>(va);
+    a->decRef();
+}
+
+void rsi_Adapter2DBindAllocation(Context *rsc, RsAdapter2D va, RsAllocation valloc)
+{
+    Adapter2D * a = static_cast<Adapter2D *>(va);
+    Allocation * alloc = static_cast<Allocation *>(valloc);
+    a->setAllocation(alloc);
+}
+
+void rsi_Adapter2DSetConstraint(Context *rsc, RsAdapter2D va, RsDimension dim, uint32_t value)
+{
+    Adapter2D * a = static_cast<Adapter2D *>(va);
+    switch(dim) {
+    case RS_DIMENSION_X:
+        rsAssert(!"Cannot contrain X in an 2D adapter");
+        return;
+    case RS_DIMENSION_Y:
+        rsAssert(!"Cannot contrain Y in an 2D adapter");
+        break;
+    case RS_DIMENSION_Z:
+        a->setZ(value);
+        break;
+    case RS_DIMENSION_LOD:
+        a->setLOD(value);
+        break;
+    case RS_DIMENSION_FACE:
+        a->setFace(value);
+        break;
+    default:
+        rsAssert(!"Unimplemented constraint");
+        return;
+    }
+}
+
+void rsi_Adapter2DData(Context *rsc, RsAdapter2D va, const void *data)
+{
+    Adapter2D * a = static_cast<Adapter2D *>(va);
+    a->data(data);
+}
+
+void rsi_Adapter2DSubData(Context *rsc, RsAdapter2D va, uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, const void *data)
+{
+    Adapter2D * a = static_cast<Adapter2D *>(va);
+    a->subData(xoff, yoff, w, h, data);
+}
+
+}
+}
diff --git a/libs/rs/rsAdapter.h b/libs/rs/rsAdapter.h
new file mode 100644
index 0000000..865535e
--- /dev/null
+++ b/libs/rs/rsAdapter.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_RS_ADAPTER_H
+#define ANDROID_RS_ADAPTER_H
+
+#include "rsAllocation.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+    
+class Adapter1D : public ObjectBase
+{
+
+public:
+    // By policy this allocation will hold a pointer to the type
+    // but will not destroy it on destruction.
+    Adapter1D();
+    Adapter1D(Allocation *);
+    void reset();
+    void * getElement(uint32_t x);
+
+    void setAllocation(Allocation *a) {mAllocation.set(a);}
+
+    uint32_t getDimX() const {return mAllocation->getType()->getLODDimX(mLOD);}
+
+    const Type * getBaseType() const {return mAllocation->getType();}
+
+    inline void setY(uint32_t y) {mY = y;}
+    inline void setZ(uint32_t z) {mZ = z;}
+    inline void setLOD(uint32_t lod) {mLOD = lod;}
+    inline void setFace(uint32_t face) {mFace = face;}
+    //void setArray(uint32_t num, uint32_t value);
+
+    void subData(uint32_t xoff, uint32_t count, const void *data);
+    void data(const void *data);
+
+protected:
+    ObjectBaseRef<Allocation> mAllocation;
+    uint32_t mY;
+    uint32_t mZ;
+    uint32_t mLOD;
+    uint32_t mFace;
+};
+
+class Adapter2D : public ObjectBase
+{
+
+public:
+    // By policy this allocation will hold a pointer to the type
+    // but will not destroy it on destruction.
+    Adapter2D();
+    Adapter2D(Allocation *);
+    void reset();
+    void * getElement(uint32_t x, uint32_t y) const;
+
+    uint32_t getDimX() const {return mAllocation->getType()->getLODDimX(mLOD);}
+    uint32_t getDimY() const {return mAllocation->getType()->getLODDimY(mLOD);}
+    const Type * getBaseType() const {return mAllocation->getType();}
+
+    void setAllocation(Allocation *a) {mAllocation.set(a);}
+    inline void setZ(uint32_t z) {mZ = z;}
+    inline void setLOD(uint32_t lod) {mLOD = lod;}
+    inline void setFace(uint32_t face) {mFace = face;}
+    //void setArray(uint32_t num, uint32_t value);
+
+    void data(const void *data); 
+    void subData(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, const void *data); 
+
+protected:
+    ObjectBaseRef<Allocation> mAllocation;
+    uint32_t mZ;
+    uint32_t mLOD;
+    uint32_t mFace;
+};
+
+
+}
+}
+#endif
+
diff --git a/libs/rs/rsAllocation.cpp b/libs/rs/rsAllocation.cpp
new file mode 100644
index 0000000..f3f2e46
--- /dev/null
+++ b/libs/rs/rsAllocation.cpp
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsContext.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+Allocation::Allocation(const Type *type)
+{
+    mPtr = NULL;
+
+    mCpuWrite = false;
+    mCpuRead = false;
+    mGpuWrite = false;
+    mGpuRead = false;
+
+    mReadWriteRatio = 0;
+    mUpdateSize = 0;
+
+    mIsTexture = false;
+    mTextureID = 0;
+
+    mIsVertexBuffer = false;
+    mBufferID = 0;
+
+    mType.set(type);
+    mPtr = malloc(mType->getSizeBytes());
+    if (!mPtr) {
+        LOGE("Allocation::Allocation, alloc failure");
+    }
+
+}
+
+Allocation::~Allocation()
+{
+}
+
+void Allocation::setCpuWritable(bool)
+{
+}
+
+void Allocation::setGpuWritable(bool)
+{
+}
+
+void Allocation::setCpuReadable(bool)
+{
+}
+
+void Allocation::setGpuReadable(bool)
+{
+}
+
+bool Allocation::fixAllocation()
+{
+    return false;
+}
+
+void Allocation::uploadToTexture(uint32_t lodOffset)
+{
+    //rsAssert(!mTextureId);
+    rsAssert(lodOffset < mType->getLODCount());
+
+    //LOGE("uploadToTexture  %i,  lod %i", mTextureID, lodOffset);
+
+    if (!mTextureID) {
+        glGenTextures(1, &mTextureID);
+    }
+    glBindTexture(GL_TEXTURE_2D, mTextureID);
+
+    Adapter2D adapt(this);
+    for(uint32_t lod = 0; (lod + lodOffset) < mType->getLODCount(); lod++) {
+        adapt.setLOD(lod+lodOffset);
+
+        uint16_t * ptr = static_cast<uint16_t *>(adapt.getElement(0,0));
+        glTexImage2D(GL_TEXTURE_2D, lod, GL_RGB, 
+                     adapt.getDimX(), adapt.getDimY(), 
+                     0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, ptr);
+    }
+}
+
+void Allocation::uploadToBufferObject()
+{
+    rsAssert(!mType->getDimY());
+    rsAssert(!mType->getDimZ());
+
+    //LOGE("uploadToTexture  %i,  lod %i", mTextureID, lodOffset);
+
+    if (!mBufferID) {
+        glGenBuffers(1, &mBufferID);
+    }
+    glBindBuffer(GL_ARRAY_BUFFER, mBufferID);
+    glBufferData(GL_ARRAY_BUFFER, mType->getSizeBytes(), getPtr(), GL_DYNAMIC_DRAW);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+}
+
+void Allocation::data(const void *data)
+{
+    memcpy(mPtr, data, mType->getSizeBytes());
+}
+
+void Allocation::subData(uint32_t xoff, uint32_t count, const void *data)
+{
+    uint32_t eSize = mType->getElementSizeBytes();
+    uint8_t * ptr = static_cast<uint8_t *>(mPtr);
+    ptr += eSize * xoff;
+    memcpy(ptr, data, count * eSize);
+}
+
+void Allocation::subData(uint32_t xoff, uint32_t yoff, 
+             uint32_t w, uint32_t h, const void *data)
+{
+    uint32_t eSize = mType->getElementSizeBytes();
+    uint32_t lineSize = eSize * w;
+    uint32_t destW = mType->getDimX();
+
+    const uint8_t *src = static_cast<const uint8_t *>(data);
+    uint8_t *dst = static_cast<uint8_t *>(mPtr);
+    dst += eSize * (xoff + yoff * destW);
+    for (uint32_t line=yoff; line < (yoff+h); line++) {
+        uint8_t * ptr = static_cast<uint8_t *>(mPtr);
+        memcpy(dst, src, lineSize);
+        src += lineSize;
+        dst += destW * eSize;
+    }
+}
+
+void Allocation::subData(uint32_t xoff, uint32_t yoff, uint32_t zoff,
+             uint32_t w, uint32_t h, uint32_t d, const void *data)
+{
+}
+
+
+
+/////////////////
+// 
+
+
+namespace android {
+namespace renderscript {
+
+RsAllocation rsi_AllocationCreateTyped(Context *rsc, RsType vtype)
+{
+    const Type * type = static_cast<const Type *>(vtype);
+
+    Allocation * alloc = new Allocation(type);
+    return alloc;
+}
+
+RsAllocation rsi_AllocationCreatePredefSized(Context *rsc, RsElementPredefined t, size_t count)
+{
+    RsElement e = rsi_ElementGetPredefined(rsc, t);
+    return rsi_AllocationCreateSized(rsc, e, count);
+}
+
+RsAllocation rsi_AllocationCreateSized(Context *rsc, RsElement e, size_t count)
+{
+    Type * type = new Type();
+    type->setDimX(count);
+    type->setElement(static_cast<Element *>(e));
+    type->compute();
+    return rsi_AllocationCreateTyped(rsc, type);
+}
+
+void rsi_AllocationUploadToTexture(Context *rsc, RsAllocation va, uint32_t baseMipLevel)
+{
+    Allocation *alloc = static_cast<Allocation *>(va);
+    alloc->uploadToTexture(baseMipLevel);
+}
+
+void rsi_AllocationUploadToBufferObject(Context *rsc, RsAllocation va)
+{
+    Allocation *alloc = static_cast<Allocation *>(va);
+    alloc->uploadToBufferObject();
+}
+
+void rsi_AllocationDestroy(Context *rsc, RsAllocation)
+{
+}
+
+static void mip(const Adapter2D &out, const Adapter2D &in)
+{
+    uint32_t w = out.getDimX();
+    uint32_t h = out.getDimY();
+
+    for (uint32_t y=0; y < w; y++) {
+        uint16_t *oPtr = static_cast<uint16_t *>(out.getElement(0, y));
+        const uint16_t *i1 = static_cast<uint16_t *>(in.getElement(0, y*2));
+        const uint16_t *i2 = static_cast<uint16_t *>(in.getElement(0, y*2+1));
+
+        for (uint32_t x=0; x < h; x++) {
+            *oPtr = rsBoxFilter565(i1[0], i1[2], i2[0], i2[1]);
+            oPtr ++;
+            i1 += 2;
+            i2 += 2;
+        }
+    }
+
+}
+
+
+RsAllocation rsi_AllocationCreateFromBitmap(Context *rsc, const char *file, bool genMips)
+{
+    typedef struct _Win3xBitmapHeader
+    {
+       uint16_t type;
+       uint32_t totalSize;
+       uint32_t reserved;
+       uint32_t offset;
+       int32_t hdrSize;            /* Size of this header in bytes */
+       int32_t width;           /* Image width in pixels */
+       int32_t height;          /* Image height in pixels */
+       int16_t planes;          /* Number of color planes */
+       int16_t bpp;             /* Number of bits per pixel */
+       /* Fields added for Windows 3.x follow this line */
+       int32_t compression;     /* Compression methods used */
+       int32_t sizeOfBitmap;    /* Size of bitmap in bytes */
+       int32_t horzResolution;  /* Horizontal resolution in pixels per meter */
+       int32_t vertResolution;  /* Vertical resolution in pixels per meter */
+       int32_t colorsUsed;      /* Number of colors in the image */
+       int32_t colorsImportant; /* Minimum number of important colors */
+    } __attribute__((__packed__)) WIN3XBITMAPHEADER;
+
+    _Win3xBitmapHeader hdr;
+
+    FILE *f = fopen(file, "rb");
+    if (f == NULL) {
+        LOGE("rsAllocationCreateFromBitmap failed to open file %s", file);
+        return NULL;
+    }
+    memset(&hdr, 0, sizeof(hdr));
+    fread(&hdr, sizeof(hdr), 1, f);
+
+    if (hdr.bpp != 24) {
+        LOGE("Unsuported BMP type");
+        fclose(f);
+        return NULL;
+    }
+
+    int32_t texWidth = rsHigherPow2(hdr.width);
+    int32_t texHeight = rsHigherPow2(hdr.height);
+
+    rsi_TypeBegin(rsc, rsi_ElementGetPredefined(rsc, RS_ELEMENT_RGB_565));
+    rsi_TypeAdd(rsc, RS_DIMENSION_X, texWidth);
+    rsi_TypeAdd(rsc, RS_DIMENSION_Y, texHeight);
+    if (genMips) {
+        rsi_TypeAdd(rsc, RS_DIMENSION_LOD, 1);
+    }
+    RsType type = rsi_TypeCreate(rsc);
+
+    RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, type);
+    Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
+    texAlloc->incRef();
+    if (texAlloc == NULL) {
+        LOGE("Memory allocation failure");
+        fclose(f);
+        return NULL;
+    }
+
+    // offset to letterbox if height is not pow2
+    Adapter2D adapt(texAlloc);
+    uint8_t * fileInBuf = new uint8_t[texWidth * 3];
+    uint32_t yOffset = (hdr.width - hdr.height) / 2;
+    uint16_t *tmp = static_cast<uint16_t *>(adapt.getElement(0, yOffset));
+
+    for (int y=0; y < hdr.height; y++) {
+        fseek(f, hdr.offset + (y*hdr.width*3), SEEK_SET);
+        fread(fileInBuf, 1, hdr.width * 3, f);
+        for(int x=0; x < hdr.width; x++) {
+            *tmp = rs888to565(fileInBuf[x*3], fileInBuf[x*3 + 1], fileInBuf[x*3 + 2]);
+            tmp++;
+        }
+    }
+
+    fclose(f);
+    delete [] fileInBuf;
+
+    if (genMips) {
+        Adapter2D adapt2(texAlloc);
+        for(uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
+            adapt.setLOD(lod);
+            adapt2.setLOD(lod + 1);
+            mip(adapt2, adapt);
+        }
+    }
+
+    return texAlloc;
+}
+
+
+void rsi_AllocationData(Context *rsc, RsAllocation va, const void *data)
+{
+    Allocation *a = static_cast<Allocation *>(va);
+    a->data(data);
+}
+
+void rsi_Allocation1DSubData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t count, const void *data)
+{
+    Allocation *a = static_cast<Allocation *>(va);
+    a->subData(xoff, count, data);
+}
+
+void rsi_Allocation2DSubData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, const void *data)
+{
+    Allocation *a = static_cast<Allocation *>(va);
+    a->subData(xoff, yoff, w, h, data);
+}
+
+
+}
+}
diff --git a/libs/rs/rsAllocation.h b/libs/rs/rsAllocation.h
new file mode 100644
index 0000000..d0b91fd
--- /dev/null
+++ b/libs/rs/rsAllocation.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_STRUCTURED_ALLOCATION_H
+#define ANDROID_STRUCTURED_ALLOCATION_H
+
+#include "rsType.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+    
+
+class Allocation : public ObjectBase
+{
+    // The graphics equilivent of malloc.  The allocation contains a structure of elements.
+
+
+public:
+    // By policy this allocation will hold a pointer to the type
+    // but will not destroy it on destruction.
+    Allocation(const Type *);
+    virtual ~Allocation();
+
+    void setCpuWritable(bool);
+    void setGpuWritable(bool);
+    void setCpuReadable(bool);
+    void setGpuReadable(bool);
+
+    bool fixAllocation();
+
+    void * getPtr() const {return mPtr;}
+    const Type * getType() const {return mType.get();}
+
+    void uploadToTexture(uint32_t lodOffset = 0);
+    uint32_t getTextureID() const {return mTextureID;}
+
+    void uploadToBufferObject();
+    uint32_t getBufferObjectID() const {return mBufferID;}
+
+
+    void data(const void *data);
+    void subData(uint32_t xoff, uint32_t count, const void *data);
+    void subData(uint32_t xoff, uint32_t yoff, 
+                 uint32_t w, uint32_t h, const void *data);
+    void subData(uint32_t xoff, uint32_t yoff, uint32_t zoff,
+                 uint32_t w, uint32_t h, uint32_t d, const void *data);
+
+protected:
+    ObjectBaseRef<const Type> mType;
+    void * mPtr;
+
+    // Usage restrictions
+    bool mCpuWrite;
+    bool mCpuRead;
+    bool mGpuWrite;
+    bool mGpuRead;
+
+    // more usage hint data from the application
+    // which can be used by a driver to pick the best memory type.
+    // Likely ignored for now
+    float mReadWriteRatio;
+    float mUpdateSize;
+
+
+    // Is this a legal structure to be used as a texture source.
+    // Initially this will require 1D or 2D and color data
+    bool mIsTexture;
+    uint32_t mTextureID;
+
+    // Is this a legal structure to be used as a vertex source.
+    // Initially this will require 1D and x(yzw).  Additional per element data
+    // is allowed.
+    bool mIsVertexBuffer;
+    uint32_t mBufferID;
+
+};
+
+}
+}
+#endif
+
diff --git a/libs/rs/rsComponent.cpp b/libs/rs/rsComponent.cpp
new file mode 100644
index 0000000..a931811
--- /dev/null
+++ b/libs/rs/rsComponent.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsComponent.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+
+Component::Component()
+{
+    mType = FLOAT;
+    mKind = NONE;
+    mIsNormalized = false;
+    mBits = 0;
+}
+
+Component::Component(
+    DataKind dk, DataType dt, 
+    bool isNormalized, uint32_t bits)
+{
+    mType = dt;
+    mKind = dk;
+    mIsNormalized = isNormalized;
+    mBits = bits;
+}
+
+Component::~Component()
+{
+}
diff --git a/libs/rs/rsComponent.h b/libs/rs/rsComponent.h
new file mode 100644
index 0000000..205e575
--- /dev/null
+++ b/libs/rs/rsComponent.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_RS_STRUCTURED_COMPONENT_H
+#define ANDROID_RS_STRUCTURED_COMPONENT_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <stdlib.h>
+
+#include "RenderScript.h"
+#include "rsObjectBase.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+class Component : public ObjectBase
+{
+public:
+    enum DataType {
+        FLOAT,
+        UNSIGNED,
+        SIGNED
+    };
+
+    enum DataKind {
+        NONE,
+        RED, GREEN, BLUE, ALPHA, LUMINANCE, INTENSITY,
+        X, Y, Z, W,
+        S, T, Q, R,
+        NX, NY, NZ,
+        INDEX,
+        USER
+    };
+
+
+    Component(DataKind dk, DataType dt, bool isNormalized, uint32_t bits);
+    virtual ~Component();
+
+    DataType getType() const {return mType;}
+    bool getIsNormalized() const {return mIsNormalized;}
+    DataKind getKind() const {return mKind;}
+    uint32_t getBits() const {return mBits;}
+
+protected:
+
+    DataType mType;
+    bool mIsNormalized;
+    DataKind mKind;
+    uint32_t mBits;
+
+private:
+    Component();
+};
+
+
+}
+}
+
+#endif //ANDROID_RS_STRUCTURED_COMPONENT_H
+
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
new file mode 100644
index 0000000..163cf4d
--- /dev/null
+++ b/libs/rs/rsContext.cpp
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsDevice.h"
+#include "rsContext.h"
+#include "rsThreadIO.h"
+
+
+using namespace android;
+using namespace android::renderscript;
+
+Context * Context::gCon = NULL;
+
+void Context::initEGL()
+{
+    mNumConfigs = -1;
+
+    EGLint s_configAttribs[] = {
+         EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+         EGL_RED_SIZE,       5,
+         EGL_GREEN_SIZE,     6,
+         EGL_BLUE_SIZE,      5,
+         EGL_DEPTH_SIZE,     16,
+         EGL_NONE
+     };
+
+     LOGE("EGL 1");
+     mDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+     LOGE("EGL 2  %p", mDisplay);
+     eglInitialize(mDisplay, &mMajorVersion, &mMinorVersion);
+     LOGE("EGL 3  %i  %i", mMajorVersion, mMinorVersion);
+     eglChooseConfig(mDisplay, s_configAttribs, &mConfig, 1, &mNumConfigs);
+     LOGE("EGL 4  %p", mConfig);
+
+     if (mWndSurface) {
+         mSurface = eglCreateWindowSurface(mDisplay, mConfig,
+                 new EGLNativeWindowSurface(mWndSurface),
+                 NULL);
+     } else {
+         mSurface = eglCreateWindowSurface(mDisplay, mConfig,
+                 android_createDisplaySurface(),
+                 NULL);
+     }
+
+     LOGE("EGL 5");
+     mContext = eglCreateContext(mDisplay, mConfig, NULL, NULL);
+     eglMakeCurrent(mDisplay, mSurface, mSurface, mContext);   
+     eglQuerySurface(mDisplay, mSurface, EGL_WIDTH, &mWidth);
+     eglQuerySurface(mDisplay, mSurface, EGL_HEIGHT, &mHeight);
+     LOGE("EGL 9");
+
+}
+
+void Context::runRootScript()
+{
+    rsAssert(mRootScript->mIsRoot);
+
+    glViewport(0, 0, 320, 480);
+    float aspectH = 480.f / 320.f;
+
+    if(mRootScript->mIsOrtho) {
+        glMatrixMode(GL_PROJECTION);
+        glLoadIdentity();
+        glOrthof(0, 320,  0, 480,  0, 1);
+        glMatrixMode(GL_MODELVIEW);
+    } else {
+        glMatrixMode(GL_PROJECTION);
+        glLoadIdentity();
+        glFrustumf(-1, 1,  -aspectH, aspectH,  1, 100);
+        glRotatef(-90, 0,0,1);
+        glTranslatef(0,  0,  -3);
+        glMatrixMode(GL_MODELVIEW);
+    }
+
+    glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity();
+
+    glDepthMask(GL_TRUE);
+    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+
+    glClearColor(mRootScript->mClearColor[0], 
+                 mRootScript->mClearColor[1],
+                 mRootScript->mClearColor[2],
+                 mRootScript->mClearColor[3]);
+    glClearDepthf(mRootScript->mClearDepth);
+    glClear(GL_COLOR_BUFFER_BIT);
+    glClear(GL_DEPTH_BUFFER_BIT);
+
+    mRootScript->run(this, 0);
+
+}
+
+void Context::setupCheck()
+{
+    if (mFragmentStore.get()) {
+        mFragmentStore->setupGL();
+    }
+    if (mFragment.get()) {
+        mFragment->setupGL();
+    }
+    if (mVertex.get()) {
+        mVertex->setupGL();
+    }
+
+}
+
+
+void * Context::threadProc(void *vrsc)
+{
+     Context *rsc = static_cast<Context *>(vrsc);
+
+     LOGE("TP 1");
+     gIO = new ThreadIO();
+
+     rsc->mServerCommands.init(128);
+     rsc->mServerReturns.init(128);
+
+     rsc->initEGL();
+
+     LOGE("TP 2");
+
+     rsc->mRunning = true;
+     while (!rsc->mExit) {
+         gIO->playCoreCommands(rsc);
+
+         if (!rsc->mRootScript.get()) {
+             continue;
+         }
+
+
+         glColor4f(1,1,1,1);
+         glEnable(GL_LIGHT0);
+
+         if (rsc->mRootScript.get()) {
+             rsc->runRootScript();
+         }
+
+         eglSwapBuffers(rsc->mDisplay, rsc->mSurface);
+
+         usleep(10000);
+     }
+
+     LOGE("TP 6");
+     glClearColor(0,0,0,0);
+     glClear(GL_COLOR_BUFFER_BIT);
+     eglSwapBuffers(rsc->mDisplay, rsc->mSurface);
+     eglTerminate(rsc->mDisplay);
+
+     LOGE("TP 7");
+
+     return NULL;
+}
+
+Context::Context(Device *dev, Surface *sur)
+{
+    LOGE("CC 1");
+    dev->addContext(this);
+    mDev = dev;
+    mRunning = false;
+    mExit = false;
+
+    mServerCommands.init(256);
+    mServerReturns.init(256);
+
+    // see comment in header
+    gCon = this;
+
+    LOGE("CC 2");
+    int status = pthread_create(&mThreadId, NULL, threadProc, this);
+    if (status) {
+        LOGE("Failed to start rs context thread.");
+    }
+
+    LOGE("CC 3");
+    mWndSurface = sur;
+    while(!mRunning) {
+        sleep(1);
+    }
+    LOGE("CC 4");
+
+
+
+}
+
+Context::~Context()
+{
+    mExit = true;
+    void *res;
+
+    LOGE("DES 1");
+    int status = pthread_join(mThreadId, &res);
+    LOGE("DES 2");
+
+    if (mDev) {
+        mDev->removeContext(this);
+    }
+    LOGE("DES 3");
+}
+
+void Context::swapBuffers()
+{
+    eglSwapBuffers(mDisplay, mSurface);
+}
+
+void rsContextSwap(RsContext vrsc)
+{
+    Context *rsc = static_cast<Context *>(vrsc);
+    rsc->swapBuffers();
+}
+
+void Context::setRootScript(Script *s)
+{
+    mRootScript.set(s);
+}
+
+void Context::setFragmentStore(ProgramFragmentStore *pfs)
+{
+    mFragmentStore.set(pfs);
+    pfs->setupGL();
+}
+
+void Context::setFragment(ProgramFragment *pf)
+{
+    mFragment.set(pf);
+    pf->setupGL();
+}
+
+void Context::setVertex(ProgramVertex *pv)
+{
+    mVertex.set(pv);
+    pv->setupGL();
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// 
+
+namespace android {
+namespace renderscript {
+
+
+void rsi_ContextBindRootScript(Context *rsc, RsScript vs)
+{
+    Script *s = static_cast<Script *>(vs);
+    rsc->setRootScript(s);
+}
+
+void rsi_ContextBindSampler(Context *rsc, uint32_t slot, RsSampler vs)
+{
+    Sampler *s = static_cast<Sampler *>(vs);
+
+    if (slot > RS_MAX_SAMPLER_SLOT) {
+        LOGE("Invalid sampler slot");
+        return;
+    }
+
+    s->bindToContext(&rsc->mStateSampler, slot);
+}
+
+void rsi_ContextBindProgramFragmentStore(Context *rsc, RsProgramFragmentStore vpfs)
+{
+    ProgramFragmentStore *pfs = static_cast<ProgramFragmentStore *>(vpfs);
+    rsc->setFragmentStore(pfs);
+}
+
+void rsi_ContextBindProgramFragment(Context *rsc, RsProgramFragment vpf)
+{
+    ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
+    rsc->setFragment(pf);
+}
+
+void rsi_ContextBindProgramVertex(Context *rsc, RsProgramVertex vpv)
+{
+    ProgramVertex *pv = static_cast<ProgramVertex *>(vpv);
+    rsc->setVertex(pv);
+}
+
+
+
+}
+}
+
+
+RsContext rsContextCreate(RsDevice vdev, void *sur, uint32_t version)
+{
+    Device * dev = static_cast<Device *>(vdev);
+    Context *rsc = new Context(dev, (Surface *)sur);
+    return rsc;
+}
+
+void rsContextDestroy(RsContext vrsc)
+{
+    Context * rsc = static_cast<Context *>(vrsc);
+    delete rsc;
+}
+
diff --git a/libs/rs/rsContext.h b/libs/rs/rsContext.h
new file mode 100644
index 0000000..9d96a06
--- /dev/null
+++ b/libs/rs/rsContext.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_RS_CONTEXT_H
+#define ANDROID_RS_CONTEXT_H
+
+#include <utils/Vector.h>
+#include <ui/EGLNativeWindowSurface.h>
+#include <ui/Surface.h>
+
+#include "rsType.h"
+#include "rsMatrix.h"
+#include "rsAllocation.h"
+#include "rsTriangleMesh.h"
+#include "rsDevice.h"
+#include "rsScriptC.h"
+#include "rsAllocation.h"
+#include "rsAdapter.h"
+#include "rsSampler.h"
+#include "rsProgramFragment.h"
+#include "rsProgramFragmentStore.h"
+#include "rsProgramVertex.h"
+
+#include "rsgApiStructs.h"
+#include "rsLocklessFifo.h"
+
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+
+class Context 
+{
+public:
+    Context(Device *, Surface *);
+    ~Context();
+
+
+    //StructuredAllocationContext mStateAllocation;
+    ElementState mStateElement;
+    TypeState mStateType;
+    SamplerState mStateSampler;
+    ProgramFragmentState mStateFragment;
+    ProgramFragmentStoreState mStateFragmentStore;
+    ProgramVertexState mStateVertex;
+
+    TriangleMeshContext mStateTriangleMesh;
+
+    ScriptCState mScriptC;
+
+    static Context * getContext() {return gCon;}
+
+    void swapBuffers();
+    void setRootScript(Script *);
+    void setVertex(ProgramVertex *);
+    void setFragment(ProgramFragment *);
+    void setFragmentStore(ProgramFragmentStore *);
+
+    void updateSurface(void *sur);
+
+    const ProgramFragment * getFragment() {return mFragment.get();}
+    const ProgramFragmentStore * getFragmentStore() {return mFragmentStore.get();}
+
+    void setupCheck();
+
+protected:
+    Device *mDev;
+
+    EGLint mNumConfigs;
+    EGLint mMajorVersion;
+    EGLint mMinorVersion;
+    EGLConfig mConfig;
+    EGLContext mContext;
+    EGLSurface mSurface;
+    EGLint mWidth;
+    EGLint mHeight;
+    EGLDisplay mDisplay;
+
+    bool mRunning;
+    bool mExit;
+
+    LocklessCommandFifo mServerCommands;
+    LocklessCommandFifo mServerReturns;
+
+    pthread_t mThreadId;
+
+    ObjectBaseRef<Script> mRootScript;
+    ObjectBaseRef<ProgramFragment> mFragment;
+    ObjectBaseRef<ProgramVertex> mVertex;
+    ObjectBaseRef<ProgramFragmentStore> mFragmentStore;
+
+private:
+    Context();
+
+    void initEGL();
+
+    void runRootScript();
+
+    static void * threadProc(void *);
+
+    // todo: put in TLS
+    static Context *gCon;
+    Surface *mWndSurface;
+};
+
+
+}
+}
+#endif
diff --git a/libs/rs/rsDevice.cpp b/libs/rs/rsDevice.cpp
new file mode 100644
index 0000000..1b3c41b
--- /dev/null
+++ b/libs/rs/rsDevice.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsDevice.h"
+#include "rsContext.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+Device::Device()
+{
+
+}
+
+Device::~Device()
+{
+
+}
+
+void Device::addContext(Context *rsc)
+{
+    mContexts.add(rsc);
+}
+
+void Device::removeContext(Context *rsc)
+{
+    for (size_t idx=0; idx < mContexts.size(); idx++) {
+        if (mContexts[idx] == rsc) {
+            mContexts.removeAt(idx);
+            break;
+        }
+    }
+}
+
+
+
+RsDevice rsDeviceCreate()
+{
+    Device * d = new Device();
+    return d;
+}
+
+void rsDeviceDestroy(RsDevice dev)
+{
+    Device * d = static_cast<Device *>(dev);
+    delete d;
+
+}
+
diff --git a/libs/rs/rsDevice.h b/libs/rs/rsDevice.h
new file mode 100644
index 0000000..3de3ffa
--- /dev/null
+++ b/libs/rs/rsDevice.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_RS_DEVICE_H
+#define ANDROID_RS_DEVICE_H
+
+#include <utils/Vector.h>
+
+//#include "StructuredComponent.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+class Context;
+
+class Device {
+public:
+    Device();
+    ~Device();
+
+    void addContext(Context *);
+    void removeContext(Context *);
+
+protected:
+    Vector<Context *> mContexts;
+
+
+};
+
+
+
+
+
+}
+}
+#endif
diff --git a/libs/rs/rsElement.cpp b/libs/rs/rsElement.cpp
new file mode 100644
index 0000000..1637544
--- /dev/null
+++ b/libs/rs/rsElement.cpp
@@ -0,0 +1,326 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsContext.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+void ElementState::initPredefined()
+{
+    Component * u_8  = new Component(Component::USER,   Component::UNSIGNED,  true,  8);
+    Component * i_8  = new Component(Component::USER,   Component::SIGNED,    true,  8);
+    Component * u_16 = new Component(Component::USER,   Component::UNSIGNED,  true,  16);
+    Component * i_16 = new Component(Component::USER,   Component::SIGNED,    true,  16);
+    Component * u_32 = new Component(Component::USER,   Component::UNSIGNED,  true,  32);
+    Component * i_32 = new Component(Component::USER,   Component::SIGNED,    true,  32);
+    Component * f_32 = new Component(Component::USER,   Component::FLOAT,     true,  32);
+
+
+    Component * r_4  = new Component(Component::RED,    Component::UNSIGNED,  true,  4);
+    Component * r_5  = new Component(Component::RED,    Component::UNSIGNED,  true,  5);
+    Component * r_8  = new Component(Component::RED,    Component::UNSIGNED,  true,  8);
+
+    Component * g_4  = new Component(Component::GREEN,  Component::UNSIGNED,  true,  4);
+    Component * g_5  = new Component(Component::GREEN,  Component::UNSIGNED,  true,  5);
+    Component * g_6  = new Component(Component::GREEN,  Component::UNSIGNED,  true,  6);
+    Component * g_8  = new Component(Component::GREEN,  Component::UNSIGNED,  true,  8);
+
+    Component * b_4  = new Component(Component::BLUE,   Component::UNSIGNED,  true,  4);
+    Component * b_5  = new Component(Component::BLUE,   Component::UNSIGNED,  true,  5);
+    Component * b_8  = new Component(Component::BLUE,   Component::UNSIGNED,  true,  8);
+
+    Component * a_1  = new Component(Component::ALPHA,  Component::UNSIGNED,  true,  1);
+    Component * a_4  = new Component(Component::ALPHA,  Component::UNSIGNED,  true,  4);
+    Component * a_8  = new Component(Component::ALPHA,  Component::UNSIGNED,  true,  8);
+
+    Component * idx_16 = new Component(Component::INDEX,  Component::UNSIGNED,  false, 16);
+    Component * idx_32 = new Component(Component::INDEX,  Component::UNSIGNED,  false, 32);
+
+    Component * x    = new Component(Component::X,      Component::FLOAT,     false, 32);
+    Component * y    = new Component(Component::Y,      Component::FLOAT,     false, 32);
+    Component * z    = new Component(Component::Z,      Component::FLOAT,     false, 32);
+
+    Component * nx   = new Component(Component::NX,     Component::FLOAT,     false, 32);
+    Component * ny   = new Component(Component::NY,     Component::FLOAT,     false, 32);
+    Component * nz   = new Component(Component::NZ,     Component::FLOAT,     false, 32);
+
+    Component * s    = new Component(Component::S,      Component::FLOAT,     false, 32);
+    Component * t    = new Component(Component::T,      Component::FLOAT,     false, 32);
+
+    Element * e;
+
+    e = new Element(1);
+    e->setComponent(0, u_8);
+    mPredefinedList.add(Predefined(RS_ELEMENT_USER_U8, e));
+
+    e = new Element(1);
+    e->setComponent(0, i_8);
+    mPredefinedList.add(Predefined(RS_ELEMENT_USER_I8, e));
+
+    e = new Element(1);
+    e->setComponent(0, u_16);
+    mPredefinedList.add(Predefined(RS_ELEMENT_USER_U16, e));
+
+    e = new Element(1);
+    e->setComponent(0, i_16);
+    mPredefinedList.add(Predefined(RS_ELEMENT_USER_I16, e));
+
+    e = new Element(1);
+    e->setComponent(0, u_32);
+    mPredefinedList.add(Predefined(RS_ELEMENT_USER_U32, e));
+
+    e = new Element(1);
+    e->setComponent(0, i_32);
+    mPredefinedList.add(Predefined(RS_ELEMENT_USER_I32, e));
+
+    e = new Element(1);
+    e->setComponent(0, f_32);
+    mPredefinedList.add(Predefined(RS_ELEMENT_USER_FLOAT, e));
+
+    e = new Element(3);
+    e->setComponent(0, r_5);
+    e->setComponent(1, g_6);
+    e->setComponent(2, b_5);
+    mPredefinedList.add(Predefined(RS_ELEMENT_RGB_565, e));
+
+    e = new Element(4);
+    e->setComponent(0, r_5);
+    e->setComponent(1, g_5);
+    e->setComponent(2, b_5);
+    e->setComponent(3, a_1);
+    mPredefinedList.add(Predefined(RS_ELEMENT_RGBA_5551, e));
+
+    e = new Element(4);
+    e->setComponent(0, r_4);
+    e->setComponent(1, g_4);
+    e->setComponent(2, b_4);
+    e->setComponent(3, a_4);
+    mPredefinedList.add(Predefined(RS_ELEMENT_RGBA_4444, e));
+
+    e = new Element(3);
+    e->setComponent(0, r_8);
+    e->setComponent(1, g_8);
+    e->setComponent(2, b_8);
+    mPredefinedList.add(Predefined(RS_ELEMENT_RGB_888, e));
+
+    e = new Element(4);
+    e->setComponent(0, r_8);
+    e->setComponent(1, g_8);
+    e->setComponent(2, b_8);
+    e->setComponent(3, a_8);
+    mPredefinedList.add(Predefined(RS_ELEMENT_RGBA_8888, e));
+
+    e = new Element(1);
+    e->setComponent(0, idx_16);
+    mPredefinedList.add(Predefined(RS_ELEMENT_INDEX_16, e));
+
+    e = new Element(1);
+    e->setComponent(0, idx_32);
+    mPredefinedList.add(Predefined(RS_ELEMENT_INDEX_32, e));
+
+    e = new Element(2);
+    e->setComponent(0, x);
+    e->setComponent(1, y);
+    mPredefinedList.add(Predefined(RS_ELEMENT_XY_F32, e));
+
+    e = new Element(3);
+    e->setComponent(0, x);
+    e->setComponent(1, y);
+    e->setComponent(2, z);
+    mPredefinedList.add(Predefined(RS_ELEMENT_XYZ_F32, e));
+
+    e = new Element(4);
+    e->setComponent(0, s);
+    e->setComponent(1, t);
+    e->setComponent(2, x);
+    e->setComponent(3, y);
+    mPredefinedList.add(Predefined(RS_ELEMENT_ST_XY_F32, e));
+
+    e = new Element(5);
+    e->setComponent(0, s);
+    e->setComponent(1, t);
+    e->setComponent(2, x);
+    e->setComponent(3, y);
+    e->setComponent(4, z);
+    mPredefinedList.add(Predefined(RS_ELEMENT_ST_XYZ_F32, e));
+
+    e = new Element(6);
+    e->setComponent(0, nx);
+    e->setComponent(1, ny);
+    e->setComponent(2, nz);
+    e->setComponent(3, x);
+    e->setComponent(4, y);
+    e->setComponent(5, z);
+    mPredefinedList.add(Predefined(RS_ELEMENT_NORM_XYZ_F32, e));
+
+    e = new Element(8);
+    e->setComponent(0, nx);
+    e->setComponent(1, ny);
+    e->setComponent(2, nz);
+    e->setComponent(3, s);
+    e->setComponent(4, t);
+    e->setComponent(5, x);
+    e->setComponent(6, y);
+    e->setComponent(7, z);
+    mPredefinedList.add(Predefined(RS_ELEMENT_NORM_ST_XYZ_F32, e));
+}
+
+
+Element::Element()
+{
+    mComponents = NULL;
+    mComponentCount = 0;
+}
+
+Element::Element(uint32_t count)
+{
+    mComponents = new ObjectBaseRef<Component> [count];
+    mComponentCount = count;
+}
+
+Element::~Element()
+{
+    clear();
+}
+
+void Element::clear()
+{
+    delete [] mComponents;
+    mComponents = NULL;
+    mComponentCount = 0;
+}
+
+void Element::setComponent(uint32_t idx, Component *c)
+{
+    rsAssert(!mComponents[idx].get());
+    rsAssert(idx < mComponentCount);
+    mComponents[idx].set(c);
+    c->incRef();
+}
+
+
+size_t Element::getSizeBits() const
+{
+    size_t total = 0;
+    for (size_t ct=0; ct < mComponentCount; ct++) {
+        total += mComponents[ct]->getBits();
+    }
+    return total;
+}
+
+size_t Element::getComponentOffsetBits(uint32_t componentNumber) const
+{
+    size_t offset = 0;
+    for (uint32_t ct = 0; ct < componentNumber; ct++) {
+        offset += mComponents[ct]->getBits();
+    }
+    return offset;
+}
+
+ElementState::ElementState()
+{
+}
+
+ElementState::~ElementState()
+{
+}
+
+/////////////////////////////////////////
+// 
+
+namespace android {
+namespace renderscript {
+
+void rsi_ElementBegin(Context *rsc)
+{
+    rsc->mStateElement.mComponentBuildList.clear();
+}
+
+void rsi_ElementAddPredefined(Context *rsc, RsElementPredefined predef)
+{
+    ElementState * sec = &rsc->mStateElement;
+
+    RsElement ve = rsi_ElementGetPredefined(rsc, predef);
+    const Element *e = static_cast<const Element *>(ve);
+
+    for(size_t ct = 0; ct < sec->mPredefinedList[predef].mElement->getComponentCount(); ct++) {
+        sec->mComponentBuildList.add(sec->mPredefinedList[predef].mElement->getComponent(ct));
+    }
+}
+
+RsElement rsi_ElementGetPredefined(Context *rsc, RsElementPredefined predef)
+{
+    ElementState * sec = &rsc->mStateElement;
+
+    if (!sec->mPredefinedList.size()) {
+        sec->initPredefined();
+    }
+
+    if ((predef < 0) || 
+        (static_cast<uint32_t>(predef) >= sec->mPredefinedList.size())) {
+        LOGE("rsElementGetPredefined: Request for bad predefined type");
+        // error
+        return NULL;
+    }
+
+    rsAssert(sec->mPredefinedList[predef].mEnum == predef);
+    Element * e = sec->mPredefinedList[predef].mElement;
+    e->incRef();
+    return e;
+}
+
+void rsi_ElementAdd(Context *rsc, RsDataKind dk, RsDataType dt, bool isNormalized, size_t bits)
+{
+    ElementState * sec = &rsc->mStateElement;
+
+}
+
+RsElement rsi_ElementCreate(Context *rsc)
+{
+    ElementState * sec = &rsc->mStateElement;
+
+    Element *se = new Element(sec->mComponentBuildList.size());
+    sec->mAllElements.add(se);
+
+    for (size_t ct = 0; ct < se->getComponentCount(); ct++) {
+        se->setComponent(ct, sec->mComponentBuildList[ct]);
+    }
+
+    rsc->mStateElement.mComponentBuildList.clear();
+    se->incRef();
+
+    LOGE("Create %p", se);
+    return se;
+}
+
+void rsi_ElementDestroy(Context *rsc, RsElement vse)
+{
+    ElementState * sec = &rsc->mStateElement;
+    Element * se = static_cast<Element *>(vse);
+
+    for (size_t ct = 0; ct < sec->mAllElements.size(); ct++) {
+        if (sec->mAllElements[ct] == se) {
+            sec->mAllElements.removeAt(ct);
+            break;
+        }
+    }
+    se->decRef();
+}
+
+
+}
+}
diff --git a/libs/rs/rsElement.h b/libs/rs/rsElement.h
new file mode 100644
index 0000000..7852ffc
--- /dev/null
+++ b/libs/rs/rsElement.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_STRUCTURED_ELEMENT_H
+#define ANDROID_STRUCTURED_ELEMENT_H
+
+#include <utils/Vector.h>
+
+#include "rsComponent.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+
+// An element is a group of Components that occupies one cell in a structure.
+class Element : public ObjectBase
+{
+public:
+    Element(uint32_t count);
+    ~Element();
+
+
+    void setComponent(uint32_t idx, Component *c);
+
+
+
+    size_t getSizeBits() const;
+    size_t getSizeBytes() const { 
+        return (getSizeBits() + 7) >> 3; 
+    }
+
+    size_t getComponentOffsetBits(uint32_t componentNumber) const;
+    size_t getComponentOffsetBytes(uint32_t componentNumber) const { 
+        return (getComponentOffsetBits(componentNumber) + 7) >> 3;
+    }
+
+    uint32_t getComponentCount() const {return mComponentCount;}
+    Component * getComponent(uint32_t idx) const {return mComponents[idx].get();}
+
+protected:
+    // deallocate any components that are part of this element.
+    void clear();
+
+    size_t mComponentCount;
+    ObjectBaseRef<Component> * mComponents;
+    //uint32_t *mOffsetTable;
+
+    Element();
+};
+
+
+class ElementState {
+public:
+    ElementState();
+    ~ElementState();
+
+    Vector<Element *> mAllElements;
+    Vector<Component *> mComponentBuildList;
+
+
+
+    struct Predefined {
+        Predefined() {
+            mElement = NULL;
+        }
+        Predefined(RsElementPredefined en, Element *e) {
+            mEnum = en; 
+            mElement = e;
+        }
+        RsElementPredefined mEnum;
+        Element * mElement;
+    };
+    Vector<Predefined> mPredefinedList;
+
+    void initPredefined();
+    
+};
+
+
+}
+}
+#endif //ANDROID_STRUCTURED_ELEMENT_H
diff --git a/libs/rs/rsLocklessFifo.cpp b/libs/rs/rsLocklessFifo.cpp
new file mode 100644
index 0000000..3f51e04
--- /dev/null
+++ b/libs/rs/rsLocklessFifo.cpp
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsLocklessFifo.h"
+
+using namespace android;
+
+#include <utils/Log.h>
+
+LocklessCommandFifo::LocklessCommandFifo()
+{
+}
+
+LocklessCommandFifo::~LocklessCommandFifo()
+{
+}
+
+bool LocklessCommandFifo::init(uint32_t sizeInBytes)
+{
+    // Add room for a buffer reset command
+    mBuffer = static_cast<uint8_t *>(malloc(sizeInBytes + 4));
+    if (!mBuffer) {
+        LOGE("LocklessFifo allocation failure");
+        return false;
+    }
+
+    int status = pthread_mutex_init(&mMutex, NULL);
+    if (status) {
+        LOGE("LocklessFifo mutex init failure");
+        free(mBuffer);
+        return false;
+    }
+    status = pthread_cond_init(&mCondition, NULL);
+    if (status) {
+        LOGE("LocklessFifo condition init failure");
+        pthread_mutex_destroy(&mMutex);
+        free(mBuffer);
+        return false;
+    }
+
+    mSize = sizeInBytes;
+    mPut = mBuffer;
+    mGet = mBuffer;
+    mEnd = mBuffer + (sizeInBytes) - 1;
+    dumpState("init");
+    return true;
+}
+
+uint32_t LocklessCommandFifo::getFreeSpace() const 
+{
+    int32_t freeSpace = 0;
+    //dumpState("getFreeSpace");
+
+    if (mPut >= mGet) {
+        freeSpace = mEnd - mPut;
+    } else {
+        freeSpace = mGet - mPut;
+    }
+
+    if (freeSpace < 0) {
+        freeSpace = 0;
+    }
+    
+    return freeSpace;
+}
+
+bool LocklessCommandFifo::isEmpty() const
+{
+    return mPut == mGet;
+}
+
+
+void * LocklessCommandFifo::reserve(uint32_t sizeInBytes)
+{
+    // Add space for command header;
+    sizeInBytes += 4;
+
+    //dumpState("reserve");
+    if (getFreeSpace() < sizeInBytes) {
+        makeSpace(sizeInBytes);
+    }
+
+    return mPut + 4;
+}
+
+void LocklessCommandFifo::commit(uint32_t command, uint32_t sizeInBytes)
+{
+    //LOGE("commit cmd %i  size %i", command, sizeInBytes);
+    //dumpState("commit 1");
+    reinterpret_cast<uint16_t *>(mPut)[0] = command;
+    reinterpret_cast<uint16_t *>(mPut)[1] = sizeInBytes;
+    mPut += ((sizeInBytes + 3) & ~3) + 4;
+    //dumpState("commit 2");
+
+}
+
+void LocklessCommandFifo::commitSync(uint32_t command, uint32_t sizeInBytes)
+{
+    commit(command, sizeInBytes);
+    flush();
+}
+
+void LocklessCommandFifo::flush()
+{
+    //dumpState("flush 1");
+    while(mPut != mGet) {
+        usleep(1);
+    }
+    //dumpState("flush 2");
+}
+
+const void * LocklessCommandFifo::get(uint32_t *command, uint32_t *bytesData)
+{
+    while(1) {
+        while(isEmpty()) {
+            usleep(10);
+        }
+        //dumpState("get 3");
+
+        *command = reinterpret_cast<const uint16_t *>(mGet)[0];
+        *bytesData = reinterpret_cast<const uint16_t *>(mGet)[1];
+        //LOGE("Got %i, %i", *command, *bytesData);
+    
+        if (*command) {
+            // non-zero command is valid
+            return mGet+4;
+        }
+    
+        // zero command means reset to beginning.
+        mGet = mBuffer;
+    }
+}
+
+void LocklessCommandFifo::next()
+{
+    uint32_t bytes = reinterpret_cast<const uint16_t *>(mGet)[1];
+    mGet += ((bytes + 3) & ~3) + 4;
+    //dumpState("next");
+}
+
+void LocklessCommandFifo::makeSpace(uint32_t bytes)
+{
+    if ((mPut+bytes) > mEnd) {
+        // Need to loop regardless of where get is.
+        while((mGet > mPut) && (mPut+4 >= mGet)) {
+            sleep(1);
+        }
+
+        // Toss in a reset then the normal wait for space will do the rest.
+        reinterpret_cast<uint16_t *>(mPut)[0] = 0;
+        reinterpret_cast<uint16_t *>(mPut)[1] = 0;
+        mPut += 4;
+    }
+
+    // it will fit here so we just need to wait for space.
+    while(getFreeSpace() < bytes) {
+        sleep(1);
+    }
+    
+}
+
+void LocklessCommandFifo::dumpState(const char *s) const
+{
+    LOGE("%s  put %p, get %p,  buf %p,  end %p", s, mPut, mGet, mBuffer, mEnd);
+}
+
+
diff --git a/libs/rs/rsLocklessFifo.h b/libs/rs/rsLocklessFifo.h
new file mode 100644
index 0000000..ddef382
--- /dev/null
+++ b/libs/rs/rsLocklessFifo.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_RS_LOCKLESS_FIFO_H
+#define ANDROID_RS_LOCKLESS_FIFO_H
+
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+namespace android {
+
+
+// A simple FIFO to be used as a producer / consumer between two
+// threads.  One is writer and one is reader.  The common cases
+// will not require locking.  It is not threadsafe for multiple 
+// readers or writers by design.
+
+class LocklessCommandFifo 
+{
+public:
+    bool init(uint32_t size);
+
+    LocklessCommandFifo();
+    ~LocklessCommandFifo();
+
+
+protected:
+    uint8_t * volatile mPut;
+    uint8_t * volatile mGet;
+    uint8_t * mBuffer;
+    uint8_t * mEnd;
+    uint8_t mSize;
+
+    pthread_mutex_t mMutex;
+    pthread_cond_t mCondition;
+
+public:
+    void * reserve(uint32_t bytes);
+    void commit(uint32_t command, uint32_t bytes);
+    void commitSync(uint32_t command, uint32_t bytes);
+
+    void flush();
+    const void * get(uint32_t *command, uint32_t *bytesData);
+    void next();
+
+    void makeSpace(uint32_t bytes);
+
+    bool isEmpty() const;
+    uint32_t getFreeSpace() const;
+
+
+private:
+    void dumpState(const char *) const;
+};
+
+
+}
+#endif
diff --git a/libs/rs/rsMatrix.cpp b/libs/rs/rsMatrix.cpp
new file mode 100644
index 0000000..7d22ae0
--- /dev/null
+++ b/libs/rs/rsMatrix.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsMatrix.h"
+
+#include "stdlib.h"
+#include "math.h"
+
+#include <utils/Log.h>
+
+using namespace android;
+using namespace android::renderscript;
+
+
+
+void Matrix::loadIdentity()
+{
+    set(0, 0, 1);
+    set(1, 0, 0);
+    set(2, 0, 0);
+    set(3, 0, 0);
+
+    set(0, 1, 0);
+    set(1, 1, 1);
+    set(2, 1, 0);
+    set(3, 1, 0);
+
+    set(0, 2, 0);
+    set(1, 2, 0);
+    set(2, 2, 1);
+    set(3, 2, 0);
+
+    set(0, 3, 0);
+    set(1, 3, 0);
+    set(2, 3, 0);
+    set(3, 3, 1);
+}
+
+void Matrix::load(const float *v)
+{
+    memcpy(m, v, sizeof(m));
+}
+
+void Matrix::load(const Matrix *v)
+{
+    memcpy(m, v->m, sizeof(m));
+}
+
+void Matrix::loadRotate(float rot, float x, float y, float z)
+{
+    float c, s;
+    m[3] = 0;
+    m[7] = 0;
+    m[11]= 0;
+    m[12]= 0;
+    m[13]= 0;
+    m[14]= 0;
+    m[15]= 1;
+    rot *= float(M_PI / 180.0f);
+    c = cosf(rot);
+    s = sinf(rot);
+
+    const float len = sqrtf(x*x + y*y + z*z);
+    if (!(len != 1)) {
+        const float recipLen = 1.f / len;
+        x *= recipLen;
+        y *= recipLen;
+        z *= recipLen;
+    }
+    const float nc = 1.0f - c;
+    const float xy = x * y;
+    const float yz = y * z;
+    const float zx = z * x;
+    const float xs = x * s;
+    const float ys = y * s;
+    const float zs = z * s;		
+    m[ 0] = x*x*nc +  c;
+    m[ 4] =  xy*nc - zs;
+    m[ 8] =  zx*nc + ys;
+    m[ 1] =  xy*nc + zs;
+    m[ 5] = y*y*nc +  c;
+    m[ 9] =  yz*nc - xs;
+    m[ 2] =  zx*nc - ys;
+    m[ 6] =  yz*nc + xs;
+    m[10] = z*z*nc +  c;
+}
+
+void Matrix::loadScale(float x, float y, float z)
+{
+    loadIdentity();
+    m[0] = x;
+    m[5] = y;
+    m[10] = z;
+}
+
+void Matrix::loadTranslate(float x, float y, float z)
+{
+    loadIdentity();
+    m[12] = x;
+    m[13] = y;
+    m[14] = z;
+}
+
+void Matrix::loadMultiply(const Matrix *lhs, const Matrix *rhs)
+{
+    for (int i=0 ; i<4 ; i++) {
+        float ri0 = 0;
+        float ri1 = 0;
+        float ri2 = 0;
+        float ri3 = 0;
+        for (int j=0 ; j<4 ; j++) {
+            const float rhs_ij = rhs->get(i,j);
+            ri0 += lhs->get(j,0) * rhs_ij;
+            ri1 += lhs->get(j,1) * rhs_ij;
+            ri2 += lhs->get(j,2) * rhs_ij;
+            ri3 += lhs->get(j,3) * rhs_ij;
+        }
+        set(i,0, ri0);
+        set(i,1, ri1);
+        set(i,2, ri2);
+        set(i,3, ri3);
+    }
+}
+
+
diff --git a/libs/rs/rsMatrix.h b/libs/rs/rsMatrix.h
new file mode 100644
index 0000000..619b494
--- /dev/null
+++ b/libs/rs/rsMatrix.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_RS_MATRIX_H
+#define ANDROID_RS_MATRIX_H
+
+
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+struct Matrix 
+{
+    float m[16];
+
+    inline float get(int i, int j) const {
+        return m[i*4 + j];
+    }
+
+    inline void set(int i, int j, float v) {
+        m[i*4 + j] = v;
+    }
+
+    void loadIdentity();
+    void load(const float *);
+    void load(const Matrix *);
+
+    void loadRotate(float rot, float x, float y, float z);
+    void loadScale(float x, float y, float z);
+    void loadTranslate(float x, float y, float z);
+    void loadMultiply(const Matrix *lhs, const Matrix *rhs);
+
+    void multiply(const Matrix *rhs) {
+        Matrix tmp;
+        tmp.loadMultiply(this, rhs);
+        load(&tmp);
+    }
+    void rotate(float rot, float x, float y, float z) {
+        Matrix tmp;
+        tmp.loadRotate(rot, x, y, z);
+        multiply(&tmp);
+    }
+    void scale(float x, float y, float z) {
+        Matrix tmp;
+        tmp.loadScale(x, y, z);
+        multiply(&tmp);
+    }
+    void translate(float x, float y, float z) {
+        Matrix tmp;
+        tmp.loadTranslate(x, y, z);
+        multiply(&tmp);
+    }
+
+
+
+};
+    
+
+
+}
+}
+
+
+
+
+#endif
+
+
+
+
diff --git a/libs/rs/rsObjectBase.cpp b/libs/rs/rsObjectBase.cpp
new file mode 100644
index 0000000..f9cb9c8
--- /dev/null
+++ b/libs/rs/rsObjectBase.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsObjectBase.h"
+#include <utils/Log.h>
+
+using namespace android;
+using namespace android::renderscript;
+
+ObjectBase::ObjectBase()
+{
+    mRefCount = 0;
+}
+
+ObjectBase::~ObjectBase()
+{
+    rsAssert(!mRefCount);
+}
+
+void ObjectBase::incRef() const
+{
+    mRefCount ++;
+    //LOGE("ObjectBase %p inc ref %i", this, mRefCount);
+}
+
+void ObjectBase::decRef() const
+{
+    rsAssert(mRefCount > 0);
+    mRefCount --;
+    //LOGE("ObjectBase %p dec ref %i", this, mRefCount);
+    if (!mRefCount) {
+        delete this;
+    }
+}
+
diff --git a/libs/rs/rsObjectBase.h b/libs/rs/rsObjectBase.h
new file mode 100644
index 0000000..7761e49
--- /dev/null
+++ b/libs/rs/rsObjectBase.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_RS_OBJECT_BASE_H
+#define ANDROID_RS_OBJECT_BASE_H
+
+#include "rsUtils.h"
+
+
+namespace android {
+namespace renderscript {
+
+// An element is a group of Components that occupies one cell in a structure.
+class ObjectBase
+{
+public:
+    ObjectBase();
+    virtual ~ObjectBase();
+
+    void incRef() const;
+    void decRef() const;
+
+private:
+    mutable int32_t mRefCount;
+
+
+};
+
+template<class T> 
+class ObjectBaseRef 
+{
+public:
+    ObjectBaseRef() {
+        mRef = NULL;
+    }
+
+    ~ObjectBaseRef() {
+        clear();
+    }
+
+    void set(T *ref) {
+        if (mRef != ref) {
+            clear();
+            mRef = ref;
+            ref->incRef();
+        }
+    }
+
+    void clear() {
+        if (mRef) {
+            mRef->decRef();
+        }
+        mRef = NULL;
+    }
+
+    inline T * get() const {
+        return mRef;
+    }
+
+    inline T * operator-> () const { 
+        return mRef;  
+    }
+
+protected:
+    T * mRef;
+
+private:
+    ObjectBaseRef(const ObjectBaseRef &) {};
+
+};
+
+
+}
+}
+
+#endif //ANDROID_RS_OBJECT_BASE_H
+
diff --git a/libs/rs/rsProgram.cpp b/libs/rs/rsProgram.cpp
new file mode 100644
index 0000000..5a83fb7
--- /dev/null
+++ b/libs/rs/rsProgram.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsContext.h"
+#include "rsProgram.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+
+Program::Program(Element *in, Element *out)
+{
+    mElementIn.set(in);
+    mElementOut.set(out);
+
+
+}
+
+Program::~Program()
+{
+}
+
+
+void Program::setAllocation(Allocation *alloc)
+{
+    mConstants.set(alloc);
+    mDirty = true;
+}
+
+void Program::setupGL()
+{
+
+}
+
+
diff --git a/libs/rs/rsProgram.h b/libs/rs/rsProgram.h
new file mode 100644
index 0000000..913fdd2
--- /dev/null
+++ b/libs/rs/rsProgram.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_RS_PROGRAM_H
+#define ANDROID_RS_PROGRAM_H
+
+#include "rsObjectBase.h"
+#include "rsElement.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+
+
+class Program : public ObjectBase
+{
+public:
+    Program(Element *in, Element *out);
+    virtual ~Program();
+
+
+    void setAllocation(Allocation *);
+
+    virtual void setupGL();
+
+protected:
+    // Components not listed in "in" will be passed though
+    // unless overwritten by components in out.
+    ObjectBaseRef<Element> mElementIn;
+    ObjectBaseRef<Element> mElementOut;
+
+    ObjectBaseRef<Allocation> mConstants;
+
+    bool mDirty;
+
+};
+
+
+
+}
+}
+#endif
+
+
+
diff --git a/libs/rs/rsProgramFragment.cpp b/libs/rs/rsProgramFragment.cpp
new file mode 100644
index 0000000..5367c53
--- /dev/null
+++ b/libs/rs/rsProgramFragment.cpp
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsContext.h"
+#include "rsProgramFragment.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+
+ProgramFragment::ProgramFragment(Element *in, Element *out) :
+    Program(in, out)
+{
+    for (uint32_t ct=0; ct < MAX_TEXTURE; ct++) {
+        mEnvModes[ct] = RS_TEX_ENV_MODE_REPLACE;
+        mTextureDimensions[ct] = 2;
+    }
+    mTextureEnableMask = 0;
+}
+
+ProgramFragment::~ProgramFragment()
+{
+}
+
+void ProgramFragment::setupGL()
+{
+    for (uint32_t ct=0; ct < MAX_TEXTURE; ct++) {
+        glActiveTexture(GL_TEXTURE0 + ct);
+        if (!(mTextureEnableMask & (1 << ct)) ||
+            !mSamplers[ct].get() ||
+            !mTextures[ct].get()) {
+
+            glDisable(GL_TEXTURE_2D);
+            continue;
+        }
+
+        glEnable(GL_TEXTURE_2D);
+        glBindTexture(GL_TEXTURE_2D, mTextures[ct]->getTextureID());
+
+        switch(mEnvModes[ct]) {
+        case RS_TEX_ENV_MODE_REPLACE:
+            glTexEnvf(GL_TEXTURE_2D, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+            break;
+        case RS_TEX_ENV_MODE_MODULATE:
+            glTexEnvf(GL_TEXTURE_2D, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+            break;
+        case RS_TEX_ENV_MODE_DECAL:
+            glTexEnvf(GL_TEXTURE_2D, GL_TEXTURE_ENV_MODE, GL_DECAL);
+            break;
+        }
+
+        mSamplers[ct]->setupGL();
+    }
+    glActiveTexture(GL_TEXTURE0);
+}
+
+
+void ProgramFragment::bindTexture(uint32_t slot, Allocation *a)
+{
+    if (slot >= MAX_TEXTURE) {
+        LOGE("Attempt to bind a texture to a slot > MAX_TEXTURE");
+        return;
+    }
+
+    mTextures[slot].set(a);
+}
+
+void ProgramFragment::bindSampler(uint32_t slot, Sampler *s)
+{
+    if (slot >= MAX_TEXTURE) {
+        LOGE("Attempt to bind a Sampler to a slot > MAX_TEXTURE");
+        return;
+    }
+
+    mSamplers[slot].set(s);
+}
+
+void ProgramFragment::setType(uint32_t slot, const Element *e, uint32_t dim)
+{
+    if (slot >= MAX_TEXTURE) {
+        LOGE("Attempt to setType to a slot > MAX_TEXTURE");
+        return;
+    }
+
+    if (dim >= 4) {
+        LOGE("Attempt to setType to a dimension > 3");
+        return;
+    }
+
+    mTextureFormats[slot].set(e);
+    mTextureDimensions[slot] = dim;
+}
+
+void ProgramFragment::setEnvMode(uint32_t slot, RsTexEnvMode env)
+{
+    if (slot >= MAX_TEXTURE) {
+        LOGE("Attempt to setEnvMode to a slot > MAX_TEXTURE");
+        return;
+    }
+
+    mEnvModes[slot] = env;
+}
+
+void ProgramFragment::setTexEnable(uint32_t slot, bool enable)
+{
+    if (slot >= MAX_TEXTURE) {
+        LOGE("Attempt to setEnvMode to a slot > MAX_TEXTURE");
+        return;
+    }
+
+    uint32_t bit = 1 << slot;
+    mTextureEnableMask &= ~bit;
+    if (enable) {
+        mTextureEnableMask |= bit;
+    }
+}
+
+
+
+ProgramFragmentState::ProgramFragmentState()
+{
+    mPF = NULL;
+}
+
+ProgramFragmentState::~ProgramFragmentState()
+{
+    delete mPF;
+
+}
+
+
+
+namespace android {
+namespace renderscript {
+
+void rsi_ProgramFragmentBegin(Context * rsc, RsElement in, RsElement out)
+{
+    delete rsc->mStateFragment.mPF;
+    rsc->mStateFragment.mPF = new ProgramFragment((Element *)in, (Element *)out);
+}
+
+void rsi_ProgramFragmentBindTexture(Context *rsc, RsProgramFragment vpf, uint32_t slot, RsAllocation a)
+{
+    ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
+    pf->bindTexture(slot, static_cast<Allocation *>(a));
+
+    //LOGE("%p %p", pf, rsc->getFragment());
+    if (pf == rsc->getFragment()) {
+        pf->setupGL();
+    }
+}
+
+void rsi_ProgramFragmentBindSampler(Context *rsc, RsProgramFragment vpf, uint32_t slot, RsSampler s)
+{
+    ProgramFragment *pf = static_cast<ProgramFragment *>(vpf);
+    pf->bindSampler(slot, static_cast<Sampler *>(s));
+
+    if (pf == rsc->getFragment()) {
+        pf->setupGL();
+    }
+}
+
+void rsi_ProgramFragmentSetType(Context *rsc, uint32_t slot, RsType vt)
+{
+    const Type *t = static_cast<const Type *>(vt);
+    uint32_t dim = 1;
+    if (t->getDimY()) {
+        dim ++;
+        if (t->getDimZ()) {
+            dim ++;
+        }
+    }
+
+    rsc->mStateFragment.mPF->setType(slot, t->getElement(), dim);
+}
+
+void rsi_ProgramFragmentSetEnvMode(Context *rsc, uint32_t slot, RsTexEnvMode env)
+{
+    rsc->mStateFragment.mPF->setEnvMode(slot, env);
+}
+
+void rsi_ProgramFragmentSetTexEnable(Context *rsc, uint32_t slot, bool enable)
+{
+    rsc->mStateFragment.mPF->setTexEnable(slot, enable);
+}
+
+RsProgramFragment rsi_ProgramFragmentCreate(Context *rsc)
+{
+    ProgramFragment *pf = rsc->mStateFragment.mPF;
+    pf->incRef();
+    rsc->mStateFragment.mPF = 0;
+    return pf;
+}
+
+
+
+}
+}
+
diff --git a/libs/rs/rsProgramFragment.h b/libs/rs/rsProgramFragment.h
new file mode 100644
index 0000000..cc08aea
--- /dev/null
+++ b/libs/rs/rsProgramFragment.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_RS_PROGRAM_FRAGMENT_H
+#define ANDROID_RS_PROGRAM_FRAGMENT_H
+
+#include "rsProgram.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+
+class ProgramFragment : public Program
+{
+public:
+    const static uint32_t MAX_TEXTURE = 2;
+    const static uint32_t MAX_CONSTANTS = 2;
+
+
+
+    ProgramFragment(Element *in, Element *out);
+    virtual ~ProgramFragment();
+
+    virtual void setupGL();
+
+
+
+    void bindTexture(uint32_t slot, Allocation *);
+    void bindSampler(uint32_t slot, Sampler *);
+    void setType(uint32_t slot, const Element *, uint32_t dim);
+
+    void setEnvMode(uint32_t slot, RsTexEnvMode);
+    void setTexEnable(uint32_t slot, bool);
+
+
+
+protected:
+    // The difference between Textures and Constants is how they are accessed
+    // Texture lookups go though a sampler which in effect converts normalized
+    // coordinates into type specific.  Multiple samples may also be taken
+    // and filtered.
+    // 
+    // Constants are strictly accessed by programetic loads.
+    ObjectBaseRef<Allocation> mTextures[MAX_TEXTURE];
+    ObjectBaseRef<Sampler> mSamplers[MAX_TEXTURE];
+    ObjectBaseRef<const Element> mTextureFormats[MAX_TEXTURE];
+    uint32_t mTextureDimensions[MAX_TEXTURE];
+
+
+    ObjectBaseRef<Allocation> mConstants[MAX_CONSTANTS];
+    ObjectBaseRef<Type> mConstantTypes[MAX_CONSTANTS];
+
+
+    // Hacks to create a program for now
+    RsTexEnvMode mEnvModes[MAX_TEXTURE];
+    uint32_t mTextureEnableMask;
+
+
+
+
+
+};
+
+class ProgramFragmentState 
+{
+public:
+    ProgramFragmentState();
+    ~ProgramFragmentState();
+
+    ProgramFragment *mPF;
+
+    ObjectBaseRef<Type> mTextureTypes[ProgramFragment::MAX_TEXTURE];
+
+
+};
+
+
+}
+}
+#endif
+
+
+
+
diff --git a/libs/rs/rsProgramFragmentStore.cpp b/libs/rs/rsProgramFragmentStore.cpp
new file mode 100644
index 0000000..7f5d5f4
--- /dev/null
+++ b/libs/rs/rsProgramFragmentStore.cpp
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsContext.h"
+#include "rsProgramFragmentStore.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+
+ProgramFragmentStore::ProgramFragmentStore(Element *in, Element *out) :
+    Program(in, out)
+{
+    mDitherEnable = true;
+    mBlendEnable = false;
+    mColorRWriteEnable = true;
+    mColorGWriteEnable = true;
+    mColorBWriteEnable = true;
+    mColorAWriteEnable = true;
+    mBlendSrc = GL_ONE;
+    mBlendDst = GL_ZERO;
+
+
+    mDepthTestEnable = false;
+    mDepthWriteEnable = true;
+    mDepthFunc = GL_LESS;
+
+
+}
+
+ProgramFragmentStore::~ProgramFragmentStore()
+{
+}
+
+void ProgramFragmentStore::setupGL()
+{
+    glColorMask(mColorRWriteEnable,
+                mColorGWriteEnable,
+                mColorBWriteEnable,
+                mColorAWriteEnable);
+    if (mBlendEnable) {
+        glEnable(GL_BLEND);
+        glBlendFunc(mBlendSrc, mBlendDst);
+    } else {
+        glDisable(GL_BLEND);
+    }
+
+    glDepthMask(mDepthWriteEnable);
+    if(mDepthTestEnable) {
+        glEnable(GL_DEPTH_TEST);
+        glDepthFunc(mDepthFunc);
+    } else {
+        glDisable(GL_DEPTH_TEST);
+    }
+
+    if (mDitherEnable) {
+        glEnable(GL_DITHER);
+    } else {
+        glDisable(GL_DITHER);
+    }
+
+
+}
+
+void ProgramFragmentStore::setDitherEnable(bool enable)
+{
+    mDitherEnable = enable;
+}
+
+void ProgramFragmentStore::setDepthFunc(RsDepthFunc func)
+{
+    mDepthTestEnable = true;
+
+    switch(func) {
+    case RS_DEPTH_FUNC_ALWAYS:
+        mDepthTestEnable = false;
+        mDepthFunc = GL_ALWAYS;
+        break;
+    case RS_DEPTH_FUNC_LESS:
+        mDepthFunc = GL_LESS;
+        break;
+    case RS_DEPTH_FUNC_LEQUAL:
+        mDepthFunc = GL_LEQUAL;
+        break;
+    case RS_DEPTH_FUNC_GREATER:
+        mDepthFunc = GL_GREATER;
+        break;
+    case RS_DEPTH_FUNC_GEQUAL:
+        mDepthFunc = GL_GEQUAL;
+        break;
+    case RS_DEPTH_FUNC_EQUAL:
+        mDepthFunc = GL_EQUAL;
+        break;
+    case RS_DEPTH_FUNC_NOTEQUAL:
+        mDepthFunc = GL_NOTEQUAL;
+        break;
+    }
+}
+
+void ProgramFragmentStore::setDepthMask(bool mask)
+{
+    mDepthWriteEnable = mask;
+}
+
+void ProgramFragmentStore::setBlendFunc(RsBlendSrcFunc src, RsBlendDstFunc dst)
+{
+    mBlendEnable = true;
+    if ((src == RS_BLEND_SRC_ONE) && 
+        (dst == RS_BLEND_DST_ZERO)) {
+        mBlendEnable = false;
+    }
+
+    switch(src) {
+    case RS_BLEND_SRC_ZERO:
+        mBlendSrc = GL_ZERO;
+        break;
+    case RS_BLEND_SRC_ONE:
+        mBlendSrc = GL_ONE;
+        break;
+    case RS_BLEND_SRC_DST_COLOR:
+        mBlendSrc = GL_DST_COLOR;
+        break;
+    case RS_BLEND_SRC_ONE_MINUS_DST_COLOR:
+        mBlendSrc = GL_ONE_MINUS_DST_COLOR;
+        break;
+    case RS_BLEND_SRC_SRC_ALPHA:
+        mBlendSrc = GL_SRC_ALPHA;
+        break;
+    case RS_BLEND_SRC_ONE_MINUS_SRC_ALPHA:
+        mBlendSrc = GL_ONE_MINUS_SRC_ALPHA;
+        break;
+    case RS_BLEND_SRC_DST_ALPHA:
+        mBlendSrc = GL_DST_ALPHA;
+        break;
+    case RS_BLEND_SRC_ONE_MINUS_DST_ALPHA:
+        mBlendSrc = GL_ONE_MINUS_DST_ALPHA;
+        break;
+    case RS_BLEND_SRC_SRC_ALPHA_SATURATE:
+        mBlendSrc = GL_SRC_ALPHA_SATURATE;
+        break;
+    }
+
+    switch(dst) {
+    case RS_BLEND_DST_ZERO:
+        mBlendDst = GL_ZERO;
+        break;
+    case RS_BLEND_DST_ONE:
+        mBlendDst = GL_ONE;
+        break;
+    case RS_BLEND_DST_SRC_COLOR:
+        mBlendDst = GL_SRC_COLOR;
+        break;
+    case RS_BLEND_DST_ONE_MINUS_SRC_COLOR:
+        mBlendDst = GL_ONE_MINUS_SRC_COLOR;
+        break;
+    case RS_BLEND_DST_SRC_ALPHA:
+        mBlendDst = GL_SRC_ALPHA;
+        break;
+    case RS_BLEND_DST_ONE_MINUS_SRC_ALPHA:
+        mBlendDst = GL_ONE_MINUS_SRC_ALPHA;
+        break;
+    case RS_BLEND_DST_DST_ALPHA:
+        mBlendDst = GL_DST_ALPHA;
+        break;
+    case RS_BLEND_DST_ONE_MINUS_DST_ALPHA:
+        mBlendDst = GL_ONE_MINUS_DST_ALPHA;
+        break;
+    }
+}
+
+void ProgramFragmentStore::setColorMask(bool r, bool g, bool b, bool a)
+{
+    mColorRWriteEnable = r;
+    mColorGWriteEnable = g;
+    mColorBWriteEnable = b;
+    mColorAWriteEnable = a;
+}
+
+
+ProgramFragmentStoreState::ProgramFragmentStoreState()
+{
+    mPFS = NULL;
+}
+
+ProgramFragmentStoreState::~ProgramFragmentStoreState()
+{
+    delete mPFS;
+
+}
+
+
+
+namespace android {
+namespace renderscript {
+
+void rsi_ProgramFragmentStoreBegin(Context * rsc, RsElement in, RsElement out)
+{
+    delete rsc->mStateFragmentStore.mPFS;
+    rsc->mStateFragmentStore.mPFS = new ProgramFragmentStore((Element *)in, (Element *)out);
+
+}
+
+void rsi_ProgramFragmentStoreDepthFunc(Context *rsc, RsDepthFunc func)
+{
+    rsc->mStateFragmentStore.mPFS->setDepthFunc(func);
+}
+
+void rsi_ProgramFragmentStoreDepthMask(Context *rsc, bool mask)
+{
+    rsc->mStateFragmentStore.mPFS->setDepthMask(mask);
+}
+
+void rsi_ProgramFragmentStoreColorMask(Context *rsc, bool r, bool g, bool b, bool a)
+{
+    rsc->mStateFragmentStore.mPFS->setColorMask(r, g, b, a);
+}
+
+void rsi_ProgramFragmentStoreBlendFunc(Context *rsc, RsBlendSrcFunc src, RsBlendDstFunc dst)
+{
+    rsc->mStateFragmentStore.mPFS->setBlendFunc(src, dst);
+}
+
+RsProgramFragmentStore rsi_ProgramFragmentStoreCreate(Context *rsc)
+{
+    ProgramFragmentStore *pfs = rsc->mStateFragmentStore.mPFS;
+    pfs->incRef();
+    rsc->mStateFragmentStore.mPFS = 0;
+
+    return pfs;
+}
+
+void rsi_ProgramFragmentStoreDither(Context *rsc, bool enable)
+{
+    rsc->mStateFragmentStore.mPFS->setDitherEnable(enable);
+}
+
+
+}
+}
diff --git a/libs/rs/rsProgramFragmentStore.h b/libs/rs/rsProgramFragmentStore.h
new file mode 100644
index 0000000..bbd0f38
--- /dev/null
+++ b/libs/rs/rsProgramFragmentStore.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_RS_PROGRAM_FRAGMENT_STORE_H
+#define ANDROID_RS_PROGRAM_FRAGMENT_STORE_H
+
+#include "rsProgram.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+
+class ProgramFragmentStore : public Program
+{
+public:
+
+
+
+    ProgramFragmentStore(Element *in, Element *out);
+    virtual ~ProgramFragmentStore();
+
+    virtual void setupGL();
+
+
+    void setDepthFunc(RsDepthFunc);
+    void setDepthMask(bool);
+
+    void setBlendFunc(RsBlendSrcFunc src, RsBlendDstFunc dst);
+    void setColorMask(bool, bool, bool, bool);
+
+    void setDitherEnable(bool);
+
+protected:
+    bool mDitherEnable;
+
+    bool mBlendEnable;
+    bool mColorRWriteEnable;
+    bool mColorGWriteEnable;
+    bool mColorBWriteEnable;
+    bool mColorAWriteEnable;
+    int32_t mBlendSrc;
+    int32_t mBlendDst;
+
+
+
+    bool mDepthTestEnable;
+    bool mDepthWriteEnable;
+    int32_t mDepthFunc;
+
+
+
+    bool mStencilTestEnable;
+
+
+
+};
+
+class ProgramFragmentStoreState 
+{
+public:
+    ProgramFragmentStoreState();
+    ~ProgramFragmentStoreState();
+
+    ProgramFragmentStore *mPFS;
+
+
+};
+
+
+}
+}
+#endif
+
+
+
diff --git a/libs/rs/rsProgramVertex.cpp b/libs/rs/rsProgramVertex.cpp
new file mode 100644
index 0000000..8e2b82d
--- /dev/null
+++ b/libs/rs/rsProgramVertex.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsContext.h"
+#include "rsProgramVertex.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+
+ProgramVertex::ProgramVertex(Element *in, Element *out) :
+    Program(in, out)
+{
+    mTextureMatrixEnable = false;
+    mProjectionEnable = false;
+    mTransformEnable = false;
+}
+
+ProgramVertex::~ProgramVertex()
+{
+}
+
+void ProgramVertex::setupGL()
+{
+    const float *f = static_cast<const float *>(mConstants[0]->getPtr());
+
+    glMatrixMode(GL_TEXTURE);
+    if (mTextureMatrixEnable) {
+        glLoadMatrixf(&f[RS_PROGRAM_VERTEX_TEXTURE_OFFSET]);
+    } else {
+        glLoadIdentity();
+    }
+
+
+    glMatrixMode(GL_PROJECTION);
+    if (mProjectionEnable) {
+        //glLoadMatrixf(&f[OFFSET_PROJECTION]);
+    } else {
+    }
+
+    glMatrixMode(GL_MODELVIEW);
+    if (mTransformEnable) {
+        glLoadMatrixf(&f[RS_PROGRAM_VERTEX_MODELVIEW_OFFSET]);
+    } else {
+        glLoadIdentity();
+    }
+
+}
+
+void ProgramVertex::setConstantType(uint32_t slot, const Type *t)
+{
+    mConstantTypes[slot].set(t);
+}
+
+void ProgramVertex::bindAllocation(uint32_t slot, Allocation *a)
+{
+    mConstants[slot].set(a);
+}
+
+
+ProgramVertexState::ProgramVertexState()
+{
+    mPV = NULL;
+}
+
+ProgramVertexState::~ProgramVertexState()
+{
+    delete mPV;
+}
+
+
+
+namespace android {
+namespace renderscript {
+
+void rsi_ProgramVertexBegin(Context *rsc, RsElement in, RsElement out)
+{
+    delete rsc->mStateVertex.mPV;
+    rsc->mStateVertex.mPV = new ProgramVertex((Element *)in, (Element *)out);
+}
+
+RsProgramVertex rsi_ProgramVertexCreate(Context *rsc)
+{
+    ProgramVertex *pv = rsc->mStateVertex.mPV;
+    pv->incRef();
+    rsc->mStateVertex.mPV = 0;
+
+    return pv;
+}
+
+void rsi_ProgramVertexBindAllocation(Context *rsc, RsProgramVertex vpgm, uint32_t slot, RsAllocation constants)
+{
+    ProgramVertex *pv = static_cast<ProgramVertex *>(vpgm);
+    pv->bindAllocation(slot, static_cast<Allocation *>(constants));
+}
+
+void rsi_ProgramVertexSetType(Context *rsc, uint32_t slot, RsType constants)
+{
+    rsc->mStateVertex.mPV->setConstantType(slot, static_cast<const Type *>(constants));
+}
+
+void rsi_ProgramVertexSetCameraMode(Context *rsc, bool ortho)
+{
+    rsc->mStateVertex.mPV->setProjectionEnabled(!ortho);
+}
+
+void rsi_ProgramVertexSetTextureMatrixEnable(Context *rsc, bool enable)
+{
+    rsc->mStateVertex.mPV->setTextureMatrixEnable(enable);
+}
+
+void rsi_ProgramVertexSetModelMatrixEnable(Context *rsc, bool enable)
+{
+    rsc->mStateVertex.mPV->setTransformEnable(enable);
+}
+
+
+
+}
+}
diff --git a/libs/rs/rsProgramVertex.h b/libs/rs/rsProgramVertex.h
new file mode 100644
index 0000000..cd46900
--- /dev/null
+++ b/libs/rs/rsProgramVertex.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_RS_PROGRAM_VERTEX_H
+#define ANDROID_RS_PROGRAM_VERTEX_H
+
+#include "rsProgram.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+
+class ProgramVertex : public Program
+{
+public:
+    const static uint32_t MAX_CONSTANTS = 2;
+
+    ProgramVertex(Element *in, Element *out);
+    virtual ~ProgramVertex();
+
+    virtual void setupGL();
+
+
+    void setConstantType(uint32_t slot, const Type *);
+    void bindAllocation(uint32_t slot, Allocation *);
+    void setTextureMatrixEnable(bool e) {mTextureMatrixEnable = e;}
+    void setProjectionEnabled(bool e) {mProjectionEnable = e;}
+    void setTransformEnable(bool e) {mTransformEnable = e;}
+
+protected:
+    bool mDirty;
+
+    ObjectBaseRef<Allocation> mConstants[MAX_CONSTANTS];
+    ObjectBaseRef<const Type> mConstantTypes[MAX_CONSTANTS];
+
+    // Hacks to create a program for now
+    bool mTextureMatrixEnable;
+    bool mProjectionEnable;
+    bool mTransformEnable;
+
+};
+
+
+class ProgramVertexState 
+{
+public:
+    ProgramVertexState();
+    ~ProgramVertexState();
+
+    ProgramVertex *mPV;
+
+    //ObjectBaseRef<Type> mTextureTypes[ProgramFragment::MAX_TEXTURE];
+
+
+};
+
+
+}
+}
+#endif
+
+
diff --git a/libs/rs/rsSampler.cpp b/libs/rs/rsSampler.cpp
new file mode 100644
index 0000000..3c008c9
--- /dev/null
+++ b/libs/rs/rsSampler.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsContext.h"
+
+
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+#include <utils/Log.h>
+
+#include "rsContext.h"
+#include "rsSampler.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+
+Sampler::Sampler()
+{
+    // Should not get called.
+    rsAssert(0);
+}
+
+Sampler::Sampler(RsSamplerValue magFilter,
+                 RsSamplerValue minFilter,
+                 RsSamplerValue wrapS,
+                 RsSamplerValue wrapT,
+                 RsSamplerValue wrapR)
+{
+    mMagFilter = magFilter;
+    mMinFilter = minFilter;
+    mWrapS = wrapS;
+    mWrapT = wrapT;
+    mWrapR = wrapR;
+}
+
+Sampler::~Sampler()
+{
+}
+
+void Sampler::setupGL()
+{
+    //LOGE("setup gl");
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+}
+
+void Sampler::bindToContext(SamplerState *ss, uint32_t slot)
+{
+    ss->mSamplers[slot].set(this);
+    mBoundSlot = slot;
+}
+
+void Sampler::unbindFromContext(SamplerState *ss)
+{
+    int32_t slot = mBoundSlot;
+    mBoundSlot = -1;
+    ss->mSamplers[slot].clear();
+}
+
+void SamplerState::setupGL()
+{
+    for (uint32_t ct=0; ct < 1/*RS_MAX_SAMPLER_SLOT*/; ct++) {
+        Sampler *s = mSamplers[ct].get();
+        if (s) {
+            s->setupGL();
+        } else {
+            glBindTexture(GL_TEXTURE_2D, 0);
+        }
+    }
+}
+
+////////////////////////////////
+
+namespace android {
+namespace renderscript {
+
+
+void rsi_SamplerBegin(Context *rsc)
+{
+    SamplerState * ss = &rsc->mStateSampler;
+
+    ss->mMagFilter = RS_SAMPLER_LINEAR;
+    ss->mMinFilter = RS_SAMPLER_LINEAR;
+    ss->mWrapS = RS_SAMPLER_WRAP;
+    ss->mWrapT = RS_SAMPLER_WRAP;
+    ss->mWrapR = RS_SAMPLER_WRAP;
+}
+
+void rsi_SamplerSet(Context *rsc, RsSamplerParam param, RsSamplerValue value)
+{
+    SamplerState * ss = &rsc->mStateSampler;
+
+    switch(param) {
+    case RS_SAMPLER_MAG_FILTER:
+        ss->mMagFilter = value;
+        break;
+    case RS_SAMPLER_MIN_FILTER:
+        ss->mMinFilter = value;
+        break;
+    case RS_SAMPLER_WRAP_S:
+        ss->mWrapS = value;
+        break;
+    case RS_SAMPLER_WRAP_T:
+        ss->mWrapT = value;
+        break;
+    case RS_SAMPLER_WRAP_R:
+        ss->mWrapR = value;
+        break;
+    }
+
+}
+
+RsSampler rsi_SamplerCreate(Context *rsc)
+{
+    SamplerState * ss = &rsc->mStateSampler;
+
+
+    Sampler * s = new Sampler(ss->mMagFilter, 
+                              ss->mMinFilter, 
+                              ss->mWrapS, 
+                              ss->mWrapT,
+                              ss->mWrapR);
+    return s;
+}
+
+}}
diff --git a/libs/rs/rsSampler.h b/libs/rs/rsSampler.h
new file mode 100644
index 0000000..45d8c61
--- /dev/null
+++ b/libs/rs/rsSampler.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_RS_SAMPLER_H
+#define ANDROID_RS_SAMPLER_H
+
+#include <math.h>
+#include <EGL/egl.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+#include "rsAllocation.h"
+#include "RenderScript.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+const static uint32_t RS_MAX_SAMPLER_SLOT = 16;
+
+class SamplerState;
+
+class Sampler : public ObjectBase
+{
+public:
+    Sampler(RsSamplerValue magFilter,
+            RsSamplerValue minFilter,
+            RsSamplerValue wrapS,
+            RsSamplerValue wrapT,
+            RsSamplerValue wrapR);
+
+    virtual ~Sampler();
+
+    void bind(Allocation *);
+    void setupGL();
+
+    void bindToContext(SamplerState *, uint32_t slot);
+    void unbindFromContext(SamplerState *);
+
+protected:
+    RsSamplerValue mMagFilter;
+    RsSamplerValue mMinFilter;
+    RsSamplerValue mWrapS;
+    RsSamplerValue mWrapT;
+    RsSamplerValue mWrapR;
+
+    int32_t mBoundSlot;
+
+private:
+    Sampler();
+
+};
+
+
+class SamplerState 
+{
+public:
+
+    RsSamplerValue mMagFilter;
+    RsSamplerValue mMinFilter;
+    RsSamplerValue mWrapS;
+    RsSamplerValue mWrapT;
+    RsSamplerValue mWrapR;
+
+
+    ObjectBaseRef<Sampler> mSamplers[RS_MAX_SAMPLER_SLOT];
+
+    void setupGL();
+
+};
+
+
+
+}
+}
+#endif //ANDROID_RS_SAMPLER_H
+
+
+
diff --git a/libs/rs/rsScript.cpp b/libs/rs/rsScript.cpp
new file mode 100644
index 0000000..24a630c
--- /dev/null
+++ b/libs/rs/rsScript.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsContext.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+Script::Script()
+{
+    mClearColor[0] = 0;
+    mClearColor[1] = 0;
+    mClearColor[2] = 0;
+    mClearColor[3] = 1;
+    mClearDepth = 1;
+}
+
+Script::~Script()
+{
+}
+
+namespace android {
+namespace renderscript {
+
+
+void rsi_ScriptDestroy(Context * rsc, RsScript vs)
+{
+    Script *s = static_cast<Script *>(vs);
+    s->decRef();
+}
+
+void rsi_ScriptBindAllocation(Context * rsc, RsScript vs, RsAllocation va, uint32_t slot)
+{
+    Script *s = static_cast<Script *>(vs);
+    s->mSlots[slot].set(static_cast<Allocation *>(va));
+}
+
+
+}
+}
+
diff --git a/libs/rs/rsScript.h b/libs/rs/rsScript.h
new file mode 100644
index 0000000..1932870
--- /dev/null
+++ b/libs/rs/rsScript.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_RS_SCRIPT_H
+#define ANDROID_RS_SCRIPT_H
+
+#include "rsAllocation.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+    
+
+class Script : public ObjectBase
+{
+public:
+
+    Script();
+    virtual ~Script();
+
+
+    bool mIsRoot;
+    bool mIsOrtho;
+
+    float mClearColor[4];
+    float mClearDepth;
+    uint32_t mClearStencil;
+
+
+    const Type * mConstantBufferTypes;
+    uint32_t mCounstantBufferCount;
+
+    ObjectBaseRef<Allocation> mSlots[16];
+
+    virtual void run(Context *, uint32_t launchID) = 0;
+};
+
+
+
+}
+}
+#endif
+
diff --git a/libs/rs/rsScriptC.cpp b/libs/rs/rsScriptC.cpp
new file mode 100644
index 0000000..f825e6e
--- /dev/null
+++ b/libs/rs/rsScriptC.cpp
@@ -0,0 +1,454 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsContext.h"
+#include "rsScriptC.h"
+#include "rsMatrix.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+
+ScriptC::ScriptC()
+{
+    mScript = NULL;
+}
+
+ScriptC::~ScriptC()
+{
+}
+
+static void matrixLoadIdentity(void *con, rsc_Matrix *mat)
+{
+    Matrix *m = reinterpret_cast<Matrix *>(mat);
+    m->loadIdentity();
+}
+
+static void matrixLoadFloat(void *con, rsc_Matrix *mat, const float *f)
+{
+    Matrix *m = reinterpret_cast<Matrix *>(mat);
+    m->load(f);
+}
+
+static void matrixLoadMat(void *con, rsc_Matrix *mat, const rsc_Matrix *newmat)
+{
+    Matrix *m = reinterpret_cast<Matrix *>(mat);
+    m->load(reinterpret_cast<const Matrix *>(newmat));
+}
+
+static void matrixLoadRotate(void *con, rsc_Matrix *mat, float rot, float x, float y, float z)
+{
+    Matrix *m = reinterpret_cast<Matrix *>(mat);
+    m->loadRotate(rot, x, y, z);
+}
+
+static void matrixLoadScale(void *con, rsc_Matrix *mat, float x, float y, float z)
+{
+    Matrix *m = reinterpret_cast<Matrix *>(mat);
+    m->loadScale(x, y, z);
+}
+
+static void matrixLoadTranslate(void *con, rsc_Matrix *mat, float x, float y, float z)
+{
+    Matrix *m = reinterpret_cast<Matrix *>(mat);
+    m->loadTranslate(x, y, z);
+}
+
+static void matrixLoadMultiply(void *con, rsc_Matrix *mat, const rsc_Matrix *lhs, const rsc_Matrix *rhs)
+{
+    Matrix *m = reinterpret_cast<Matrix *>(mat);
+    m->loadMultiply(reinterpret_cast<const Matrix *>(lhs),
+                    reinterpret_cast<const Matrix *>(rhs));
+}
+
+static void matrixMultiply(void *con, rsc_Matrix *mat, const rsc_Matrix *rhs)
+{
+    Matrix *m = reinterpret_cast<Matrix *>(mat);
+    m->multiply(reinterpret_cast<const Matrix *>(rhs));
+}
+
+static void matrixRotate(void *con, rsc_Matrix *mat, float rot, float x, float y, float z)
+{
+    Matrix *m = reinterpret_cast<Matrix *>(mat);
+    m->rotate(rot, x, y, z);
+}
+
+static void matrixScale(void *con, rsc_Matrix *mat, float x, float y, float z)
+{
+    Matrix *m = reinterpret_cast<Matrix *>(mat);
+    m->scale(x, y, z);
+}
+
+static void matrixTranslate(void *con, rsc_Matrix *mat, float x, float y, float z)
+{
+    Matrix *m = reinterpret_cast<Matrix *>(mat);
+    m->translate(x, y, z);
+}
+
+
+static const void * loadVp(void *vp, uint32_t bank, uint32_t offset)
+{
+    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
+    return &static_cast<const uint8_t *>(env->mScript->mSlots[bank]->getPtr())[offset];
+}
+
+static float loadF(void *vp, uint32_t bank, uint32_t offset)
+{
+    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
+    //LOGE("bank %i, offset %i", bank, offset);
+    //LOGE("%p", env->mScript->mSlots[bank]->getPtr());
+    return static_cast<const float *>(env->mScript->mSlots[bank]->getPtr())[offset];
+}
+
+static int32_t loadI32(void *vp, uint32_t bank, uint32_t offset)
+{
+    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
+    return static_cast<const int32_t *>(env->mScript->mSlots[bank]->getPtr())[offset];
+}
+
+static uint32_t loadU32(void *vp, uint32_t bank, uint32_t offset)
+{
+    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
+    return static_cast<const uint32_t *>(env->mScript->mSlots[bank]->getPtr())[offset];
+}
+
+static void loadEnvVec4(void *vp, uint32_t bank, uint32_t offset, rsc_Vector4 *v)
+{
+    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
+    memcpy(v, &static_cast<const float *>(env->mScript->mSlots[bank]->getPtr())[offset], sizeof(rsc_Vector4));
+}
+
+static void loadEnvMatrix(void *vp, uint32_t bank, uint32_t offset, rsc_Matrix *m)
+{
+    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
+    memcpy(m, &static_cast<const float *>(env->mScript->mSlots[bank]->getPtr())[offset], sizeof(rsc_Matrix));
+}
+
+
+static void storeF(void *vp, uint32_t bank, uint32_t offset, float v)
+{
+    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
+    static_cast<float *>(env->mScript->mSlots[bank]->getPtr())[offset] = v;
+}
+
+static void storeI32(void *vp, uint32_t bank, uint32_t offset, int32_t v)
+{
+    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
+    static_cast<int32_t *>(env->mScript->mSlots[bank]->getPtr())[offset] = v;
+}
+
+static void storeU32(void *vp, uint32_t bank, uint32_t offset, uint32_t v)
+{
+    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
+    static_cast<uint32_t *>(env->mScript->mSlots[bank]->getPtr())[offset] = v;
+}
+
+static void storeEnvVec4(void *vp, uint32_t bank, uint32_t offset, const rsc_Vector4 *v)
+{
+    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
+    memcpy(&static_cast<float *>(env->mScript->mSlots[bank]->getPtr())[offset], v, sizeof(rsc_Vector4));
+}
+
+static void storeEnvMatrix(void *vp, uint32_t bank, uint32_t offset, const rsc_Matrix *m)
+{
+    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
+    memcpy(&static_cast<float *>(env->mScript->mSlots[bank]->getPtr())[offset], m, sizeof(rsc_Matrix));
+}
+
+
+static void color(void *vp, float r, float g, float b, float a)
+{
+    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
+    glColor4f(r, g, b, a);
+}
+
+static void renderTriangleMesh(void *vp, RsTriangleMesh mesh)
+{
+    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
+    rsi_TriangleMeshRender(env->mContext, mesh);
+}
+
+static void renderTriangleMeshRange(void *vp, RsTriangleMesh mesh, uint32_t start, uint32_t count)
+{
+    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
+    rsi_TriangleMeshRenderRange(env->mContext, mesh, start, count);
+}
+
+static void materialDiffuse(void *vp, float r, float g, float b, float a)
+{
+    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
+    float v[] = {r, g, b, a};
+    glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, v);
+}
+
+static void materialSpecular(void *vp, float r, float g, float b, float a)
+{
+    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
+    float v[] = {r, g, b, a};
+    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, v);
+}
+
+static void lightPosition(void *vp, float x, float y, float z, float w)
+{
+    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
+    float v[] = {x, y, z, w};
+    glLightfv(GL_LIGHT0, GL_POSITION, v);
+}
+
+static void materialShininess(void *vp, float s)
+{
+    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
+    glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &s);
+}
+
+static void uploadToTexture(void *vp, RsAllocation va, uint32_t baseMipLevel)
+{
+    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
+    rsi_AllocationUploadToTexture(env->mContext, va, baseMipLevel);
+}
+
+static void enable(void *vp, uint32_t p)
+{
+    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
+    glEnable(p);
+}
+
+static void disable(void *vp, uint32_t p)
+{
+    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
+    glDisable(p);
+}
+
+static uint32_t scriptRand(void *vp, uint32_t max)
+{
+    return (uint32_t)(((float)rand()) * max / RAND_MAX);
+}
+
+// Assumes (GL_FIXED) x,y,z (GL_UNSIGNED_BYTE)r,g,b,a
+static void drawTriangleArray(void *vp, RsAllocation alloc, uint32_t count)
+{
+    const Allocation *a = (const Allocation *)alloc;
+    const uint32_t *ptr = (const uint32_t *)a->getPtr();
+
+    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
+    env->mContext->setupCheck();
+
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    //glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tm->mBufferObjects[1]);
+
+    glEnableClientState(GL_VERTEX_ARRAY);
+    glDisableClientState(GL_NORMAL_ARRAY);
+    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+    glEnableClientState(GL_COLOR_ARRAY);
+
+    glVertexPointer(2, GL_FIXED, 12, ptr + 1);
+    //glTexCoordPointer(2, GL_FIXED, 24, ptr + 1);
+    glColorPointer(4, GL_UNSIGNED_BYTE, 12, ptr);
+
+    glDrawArrays(GL_TRIANGLES, 0, count * 3);
+}
+
+static void pfBindTexture(void *vp, RsProgramFragment vpf, uint32_t slot, RsAllocation va)
+{
+    //LOGE("pfBindTexture %p", vpf);
+    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
+    rsi_ProgramFragmentBindTexture(env->mContext, 
+                                   static_cast<ProgramFragment *>(vpf),
+                                   slot,
+                                   static_cast<Allocation *>(va));
+
+}
+
+static void pfBindSampler(void *vp, RsProgramFragment vpf, uint32_t slot, RsSampler vs)
+{
+    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
+    rsi_ProgramFragmentBindSampler(env->mContext, 
+                                   static_cast<ProgramFragment *>(vpf),
+                                   slot,
+                                   static_cast<Sampler *>(vs));
+
+}
+
+static void contextBindProgramFragmentStore(void *vp, RsProgramFragmentStore pfs)
+{
+    //LOGE("contextBindProgramFragmentStore %p", pfs);
+    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
+    rsi_ContextBindProgramFragmentStore(env->mContext, pfs);
+
+}
+
+static void contextBindProgramFragment(void *vp, RsProgramFragment pf)
+{
+    //LOGE("contextBindProgramFragment %p", pf);
+    ScriptC::Env * env = static_cast<ScriptC::Env *>(vp);
+    rsi_ContextBindProgramFragment(env->mContext, pf);
+
+}
+
+
+static rsc_FunctionTable scriptCPtrTable = {
+    loadVp,
+    loadF,
+    loadI32,
+    loadU32,
+    loadEnvVec4,
+    loadEnvMatrix,
+
+    storeF,
+    storeI32,
+    storeU32,
+    storeEnvVec4,
+    storeEnvMatrix,
+
+    matrixLoadIdentity,
+    matrixLoadFloat,
+    matrixLoadMat,
+    matrixLoadRotate,
+    matrixLoadScale,
+    matrixLoadTranslate,
+    matrixLoadMultiply,
+    matrixMultiply,
+    matrixRotate,
+    matrixScale,
+    matrixTranslate,
+
+    color,
+    renderTriangleMesh,
+    renderTriangleMeshRange,
+
+    pfBindTexture,
+    pfBindSampler,
+
+    materialDiffuse,
+    materialSpecular,
+    lightPosition,
+    materialShininess,
+    uploadToTexture,
+    enable,
+    disable,
+
+    scriptRand,
+    drawTriangleArray,
+    contextBindProgramFragment,
+    contextBindProgramFragmentStore
+};
+
+
+void ScriptC::run(Context *rsc, uint32_t launchID)
+{
+    Env e = {rsc, this};
+    mScript(&e, &scriptCPtrTable, launchID);
+}
+
+ScriptCState::ScriptCState()
+{
+    clear();
+}
+
+ScriptCState::~ScriptCState()
+{
+}
+
+void ScriptCState::clear()
+{
+    mConstantBufferTypes.clear();
+    mClearColor[0] = 0;
+    mClearColor[1] = 0;
+    mClearColor[2] = 0;
+    mClearColor[3] = 1;
+    mClearDepth = 1;
+    mClearStencil = 0;
+    mScript = NULL;
+    mIsRoot = false;
+    mIsOrtho = true;
+}
+
+namespace android {
+namespace renderscript {
+
+void rsi_ScriptCBegin(Context * rsc)
+{
+    ScriptCState *ss = &rsc->mScriptC;
+    ss->clear();
+}
+
+void rsi_ScriptCSetClearColor(Context * rsc, float r, float g, float b, float a)
+{
+    ScriptCState *ss = &rsc->mScriptC;
+    ss->mClearColor[0] = r;
+    ss->mClearColor[1] = g;
+    ss->mClearColor[2] = b;
+    ss->mClearColor[3] = a;
+}
+
+void rsi_ScriptCSetClearDepth(Context * rsc, float v)
+{
+    ScriptCState *ss = &rsc->mScriptC;
+    ss->mClearDepth = v;
+}
+
+void rsi_ScriptCSetClearStencil(Context * rsc, uint32_t v)
+{
+    ScriptCState *ss = &rsc->mScriptC;
+    ss->mClearStencil = v;
+}
+
+void rsi_ScriptCAddType(Context * rsc, RsType vt)
+{
+    ScriptCState *ss = &rsc->mScriptC;
+    ss->mConstantBufferTypes.add(static_cast<const Type *>(vt));
+}
+
+void rsi_ScriptCSetScript(Context * rsc, void *vp)
+{
+    ScriptCState *ss = &rsc->mScriptC;
+    ss->mScript = reinterpret_cast<rsc_RunScript>(vp);
+}
+
+void rsi_ScriptCSetRoot(Context * rsc, bool isRoot)
+{
+    ScriptCState *ss = &rsc->mScriptC;
+    ss->mIsRoot = isRoot;
+}
+
+void rsi_ScriptCSetOrtho(Context * rsc, bool isOrtho)
+{
+    ScriptCState *ss = &rsc->mScriptC;
+    ss->mIsOrtho = isOrtho;
+}
+
+RsScript rsi_ScriptCCreate(Context * rsc)
+{
+    ScriptCState *ss = &rsc->mScriptC;
+
+    ScriptC *s = new ScriptC();
+    s->mScript = ss->mScript;
+    s->mClearColor[0] = ss->mClearColor[0];
+    s->mClearColor[1] = ss->mClearColor[1];
+    s->mClearColor[2] = ss->mClearColor[2];
+    s->mClearColor[3] = ss->mClearColor[3];
+    s->mClearDepth = ss->mClearDepth;
+    s->mClearStencil = ss->mClearStencil;
+    s->mIsRoot = ss->mIsRoot;
+    s->mIsOrtho = ss->mIsOrtho;
+
+    return s;
+}
+
+}
+}
+
+
diff --git a/libs/rs/rsScriptC.h b/libs/rs/rsScriptC.h
new file mode 100644
index 0000000..f35a130
--- /dev/null
+++ b/libs/rs/rsScriptC.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_RS_SCRIPT_C_H
+#define ANDROID_RS_SCRIPT_C_H
+
+#include "rsScript.h"
+
+#include "RenderScriptEnv.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+    
+
+class ScriptC : public Script
+{
+public:
+
+    ScriptC();
+    virtual ~ScriptC();
+
+
+    virtual void run(Context *, uint32_t launchID);
+
+
+    rsc_RunScript mScript;
+
+
+    struct Env {
+        Context *mContext;
+        ScriptC *mScript;
+    };
+
+};
+
+class ScriptCState 
+{
+public:
+    ScriptCState();
+    ~ScriptCState();
+
+
+    rsc_RunScript mScript;
+    float mClearColor[4];
+    float mClearDepth;
+    uint32_t mClearStencil;
+    bool mIsRoot;
+    bool mIsOrtho;
+
+    Vector<const Type *> mConstantBufferTypes;
+
+    void clear();
+};
+
+
+}
+}
+#endif
+
+
+
diff --git a/libs/rs/rsThreadIO.cpp b/libs/rs/rsThreadIO.cpp
new file mode 100644
index 0000000..d5ac70b
--- /dev/null
+++ b/libs/rs/rsThreadIO.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsContext.h"
+
+#include <utils/Log.h>
+
+#include "rsThreadIO.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+ThreadIO *android::renderscript::gIO = NULL;
+
+ThreadIO::ThreadIO()
+{
+    mToCore.init(16 * 1024);
+}
+
+ThreadIO::~ThreadIO()
+{
+}
+
+void ThreadIO::playCoreCommands(Context *con)
+{
+    //LOGE("playCoreCommands 1");
+    uint32_t cmdID = 0;
+    uint32_t cmdSize = 0;
+    while(!mToCore.isEmpty()) {
+        //LOGE("playCoreCommands 2");
+        const void * data = mToCore.get(&cmdID, &cmdSize);
+        //LOGE("playCoreCommands 3 %i %i", cmdID, cmdSize);
+
+        gPlaybackFuncs[cmdID](con, data);
+        //LOGE("playCoreCommands 4");
+
+        mToCore.next();
+        //LOGE("playCoreCommands 5");
+    }
+}
+
+
diff --git a/libs/rs/rsThreadIO.h b/libs/rs/rsThreadIO.h
new file mode 100644
index 0000000..f8ba37d
--- /dev/null
+++ b/libs/rs/rsThreadIO.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_RS_THREAD_IO_H
+#define ANDROID_RS_THREAD_IO_H
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "RenderScript.h"
+
+#include "rsLocklessFifo.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+class Context;
+
+class ThreadIO {
+public:
+    ThreadIO();
+    ~ThreadIO();
+
+    void playCoreCommands(Context *con);
+
+
+    LocklessCommandFifo mToCore;
+    //LocklessCommandFifo mToClient;
+
+    intptr_t mToCoreRet;
+
+};
+
+extern ThreadIO *gIO;
+
+
+
+}
+}
+#endif
+
diff --git a/libs/rs/rsTriangleMesh.cpp b/libs/rs/rsTriangleMesh.cpp
new file mode 100644
index 0000000..6595ebc
--- /dev/null
+++ b/libs/rs/rsTriangleMesh.cpp
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsContext.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+#include <utils/Log.h>
+
+TriangleMesh::TriangleMesh()
+{
+    mVertexElement = NULL;
+    mIndexElement = NULL;
+    mVertexData = NULL;
+    mIndexData = NULL;
+    mTriangleCount = 0;
+    mVertexDataSize = 0;
+    mIndexDataSize = 0;
+
+    mBufferObjects[0] = 0;
+    mBufferObjects[1] = 0;
+
+    mOffsetCoord = 0;
+    mOffsetTex = 0;
+    mOffsetNorm = 0;
+
+    mSizeCoord = 0;
+    mSizeTex = 0;
+    mSizeNorm = 0;
+
+}
+
+TriangleMesh::~TriangleMesh()
+{
+    free(mVertexData);
+    free(mIndexData);
+}
+
+
+
+TriangleMeshContext::TriangleMeshContext()
+{
+    clear();
+}
+
+TriangleMeshContext::~TriangleMeshContext()
+{
+}
+
+void TriangleMeshContext::clear()
+{
+    mVertexElement = NULL;
+    mVertexSizeBits = 0;
+    mIndexElement = NULL;
+    mIndexSizeBits = 0;
+    mTriangleCount = 0;
+    mVertexData.clear();
+    mIndexData.clear();
+}
+
+void TriangleMesh::analyzeElement()
+{
+    for (uint32_t ct=0; ct < mVertexElement->getComponentCount(); ct++) {
+        const Component *c = mVertexElement->getComponent(ct);
+
+        if (c->getKind() == Component::X) {
+            rsAssert(mSizeCoord == 0);
+            mSizeCoord = 1;
+            mOffsetCoord = ct;
+        }
+        if (c->getKind() == Component::Y) {
+            rsAssert(mSizeCoord == 1);
+            mSizeCoord = 2;
+        }
+        if (c->getKind() == Component::Z) {
+            rsAssert(mSizeCoord == 2);
+            mSizeCoord = 3;
+        }
+        if (c->getKind() == Component::W) {
+            rsAssert(mSizeCoord == 4);
+            mSizeCoord = 4;
+        }
+
+        if (c->getKind() == Component::NX) {
+            rsAssert(mSizeNorm == 0);
+            mSizeNorm = 1;
+            mOffsetNorm = ct;
+        }
+        if (c->getKind() == Component::NY) {
+            rsAssert(mSizeNorm == 1);
+            mSizeNorm = 2;
+        }
+        if (c->getKind() == Component::NZ) {
+            rsAssert(mSizeNorm == 2);
+            mSizeNorm = 3;
+        }
+
+        if (c->getKind() == Component::S) {
+            rsAssert(mSizeTex == 0);
+            mSizeTex = 1;
+            mOffsetTex = ct;
+        }
+        if (c->getKind() == Component::T) {
+            rsAssert(mSizeTex == 1);
+            mSizeTex = 2;
+        }
+    }
+    LOGE("TriangleMesh %i,%i  %i,%i  %i,%i", mSizeCoord, mOffsetCoord, mSizeNorm, mOffsetNorm, mSizeTex, mOffsetTex);
+
+}
+
+
+namespace android {
+namespace renderscript {
+
+void rsi_TriangleMeshBegin(Context *rsc, RsElement vertex, RsElement index)
+{
+    //LOGE("tmb  %p %p", vertex, index);
+    TriangleMeshContext *tmc = &rsc->mStateTriangleMesh;
+
+    tmc->clear();
+    tmc->mVertexElement = static_cast<Element *>(vertex);
+    tmc->mVertexSizeBits = tmc->mVertexElement->getSizeBits();
+    tmc->mIndexElement = static_cast<Element *>(index);
+    tmc->mIndexSizeBits = tmc->mIndexElement->getSizeBits();
+
+    //LOGE("Element sizes  %i  %i", tmc->mVertexSizeBits, tmc->mIndexSizeBits);
+
+    assert(!(tmc->mVertexSizeBits & 0x7));
+    assert(!(tmc->mIndexSizeBits & 0x7));
+}
+
+void rsi_TriangleMeshAddVertex(Context *rsc, const void *data)
+{
+    TriangleMeshContext *tmc = &rsc->mStateTriangleMesh;
+
+    // todo: Make this efficient.
+    for (uint32_t ct = 0; (ct * 8) < tmc->mVertexSizeBits; ct++) {
+        tmc->mVertexData.add(static_cast<const uint8_t *>(data) [ct]);
+    }
+}
+
+void rsi_TriangleMeshAddTriangle(Context *rsc, uint32_t idx1, uint32_t idx2, uint32_t idx3)
+{
+    TriangleMeshContext *tmc = &rsc->mStateTriangleMesh;
+
+    // todo: Make this efficient.
+    switch(tmc->mIndexSizeBits) {
+    case 16:
+        tmc->mIndexData.add(idx1);
+        tmc->mIndexData.add(idx2);
+        tmc->mIndexData.add(idx3);
+        break;
+    default:
+        assert(0);
+    }
+
+    tmc->mTriangleCount++;
+}
+
+RsTriangleMesh rsi_TriangleMeshCreate(Context *rsc)
+{
+    TriangleMeshContext *tmc = &rsc->mStateTriangleMesh;
+
+    TriangleMesh * tm = new TriangleMesh();
+    if (!tm) {
+        LOGE("rsTriangleMeshCreate: Error OUT OF MEMORY");
+        // error
+        return 0;
+    }
+
+    tm->mTriangleCount = tmc->mTriangleCount;
+    tm->mIndexDataSize = tmc->mIndexData.size() * tmc->mIndexSizeBits >> 3;
+    tm->mVertexDataSize = tmc->mVertexData.size();
+    tm->mIndexElement = tmc->mIndexElement;
+    tm->mVertexElement = tmc->mVertexElement;
+
+    tm->mIndexData = malloc(tm->mIndexDataSize);
+    tm->mVertexData = malloc(tm->mVertexDataSize);
+    if (!tm->mIndexData || !tm->mVertexData) {
+        LOGE("rsTriangleMeshCreate: Error OUT OF MEMORY");
+        delete tm;
+        return 0;
+    }
+
+    LOGE("Create mesh, triangleCount %i", tm->mTriangleCount);
+
+    memcpy(tm->mVertexData, tmc->mVertexData.array(), tm->mVertexDataSize);
+    memcpy(tm->mIndexData, tmc->mIndexData.array(), tm->mIndexDataSize);
+    tm->analyzeElement();
+
+    return tm;
+}
+
+void rsi_TriangleMeshDestroy(Context *rsc, RsTriangleMesh vtm)
+{
+    TriangleMeshContext *tmc = &rsc->mStateTriangleMesh;
+    TriangleMesh * tm = static_cast<TriangleMesh *>(vtm);
+
+    free(tm->mIndexData);
+    free(tm->mVertexData);
+    delete tm;
+}
+
+
+
+void rsi_TriangleMeshRenderRange(Context *rsc, RsTriangleMesh vtm, uint32_t first, uint32_t count)
+{
+    TriangleMesh * tm = static_cast<TriangleMesh *>(vtm);
+
+    rsc->setupCheck();
+
+    //LOGE("1  %p   ", vtm);
+    //LOGE("1.1  %p   %p", tm->mVertexData,  tm->mIndexData);
+    if (!tm->mBufferObjects[0]) {
+        glGenBuffers(2, &tm->mBufferObjects[0]);
+
+        glBindBuffer(GL_ARRAY_BUFFER, tm->mBufferObjects[0]);
+        glBufferData(GL_ARRAY_BUFFER, tm->mVertexDataSize, tm->mVertexData, GL_STATIC_DRAW);
+        glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tm->mBufferObjects[1]);
+        glBufferData(GL_ELEMENT_ARRAY_BUFFER, tm->mIndexDataSize, tm->mIndexData, GL_STATIC_DRAW);
+        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+    }
+
+    //LOGE("1.2");
+    if (first >= tm->mTriangleCount) {
+        return;
+    }
+    if (count >= (tm->mTriangleCount - first)) {
+        count = tm->mTriangleCount - first;
+    }
+    if (!count) {
+        return;
+    }
+
+    const float *f = (const float *)tm->mVertexData;
+
+    //LOGE("2");
+    glBindBuffer(GL_ARRAY_BUFFER, tm->mBufferObjects[0]);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, tm->mBufferObjects[1]);
+
+    glEnableClientState(GL_VERTEX_ARRAY);
+    glVertexPointer(tm->mSizeCoord, 
+                    GL_FLOAT, 
+                    tm->mVertexElement->getSizeBytes(), 
+                    (void *)tm->mVertexElement->getComponentOffsetBytes(tm->mOffsetCoord));
+
+    if (tm->mSizeTex) {
+        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+        glTexCoordPointer(tm->mSizeTex, 
+                          GL_FLOAT, 
+                          tm->mVertexElement->getSizeBytes(), 
+                          (void *)tm->mVertexElement->getComponentOffsetBytes(tm->mOffsetTex));
+    } else {
+        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+    }
+
+    if (tm->mSizeNorm) {
+        glEnableClientState(GL_NORMAL_ARRAY);
+        glNormalPointer(GL_FLOAT, 
+                        tm->mVertexElement->getSizeBytes(), 
+                        (void *)tm->mVertexElement->getComponentOffsetBytes(tm->mOffsetNorm));
+    } else {
+        glDisableClientState(GL_NORMAL_ARRAY);
+    }
+
+    glDrawElements(GL_TRIANGLES, count * 3, GL_UNSIGNED_SHORT, (GLvoid *)(first * 3 * 2));
+
+    //LOGE("4");
+
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+}
+
+void rsi_TriangleMeshRender(Context *rsc, RsTriangleMesh vtm)
+{
+    rsi_TriangleMeshRenderRange(rsc, vtm, 0, 0xffffff);
+}
+
+}}
diff --git a/libs/rs/rsTriangleMesh.h b/libs/rs/rsTriangleMesh.h
new file mode 100644
index 0000000..67f964f
--- /dev/null
+++ b/libs/rs/rsTriangleMesh.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_RS_TRIANGLE_MESH_H
+#define ANDROID_RS_TRIANGLE_MESH_H
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <math.h>
+#include <EGL/egl.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+
+#include <utils/Vector.h>
+
+#include "RenderScript.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+
+// An element is a group of Components that occupies one cell in a structure.
+class TriangleMesh
+{
+public:
+    TriangleMesh();
+    ~TriangleMesh();
+
+    const Element * mVertexElement;
+    const Element * mIndexElement;
+
+    void * mVertexData;
+    void * mIndexData;
+
+    size_t mVertexDataSize;
+    size_t mIndexDataSize;
+    uint32_t mTriangleCount;
+
+    size_t mOffsetCoord;
+    size_t mOffsetTex;
+    size_t mOffsetNorm;
+
+    size_t mSizeCoord;
+    size_t mSizeTex;
+    size_t mSizeNorm;
+
+    // GL buffer info
+    GLuint mBufferObjects[2];
+
+    void analyzeElement();
+protected:
+};
+
+class TriangleMeshContext
+{
+public:
+    TriangleMeshContext();
+    ~TriangleMeshContext();
+
+    const Element * mVertexElement;
+    const Element * mIndexElement;
+    size_t mVertexSizeBits;
+    size_t mIndexSizeBits;
+
+    Vector<uint8_t> mVertexData; 
+    Vector<uint16_t> mIndexData; 
+
+    uint32_t mTriangleCount;
+
+    void clear();
+};
+
+
+}
+}
+#endif //ANDROID_RS_TRIANGLE_MESH_H
+
diff --git a/libs/rs/rsType.cpp b/libs/rs/rsType.cpp
new file mode 100644
index 0000000..6b99820
--- /dev/null
+++ b/libs/rs/rsType.cpp
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "rsContext.h"
+
+using namespace android;
+using namespace android::renderscript;
+
+Type::Type()
+{
+    mLODs = 0;
+    mLODCount = 0;
+    clear();
+}
+
+Type::~Type()
+{
+    if (mLODs) {
+        delete [] mLODs;
+    }
+}
+
+void Type::clear()
+{
+    if (mLODs) {
+        delete [] mLODs;
+        mLODs = NULL;
+    }
+    mDimX = 0;
+    mDimY = 0;
+    mDimZ = 0;
+    mDimLOD = 0;
+    mFaces = false;
+    mElement.clear();
+}
+
+TypeState::TypeState()
+{
+}
+
+TypeState::~TypeState()
+{
+}
+
+size_t Type::getOffsetForFace(uint32_t face) const
+{
+    rsAssert(mFaces);
+    return 0;
+}
+
+void Type::compute()
+{
+    //LOGE("compute");
+    uint32_t oldLODCount = mLODCount;
+    if (mDimLOD) {
+        uint32_t l2x = rsFindHighBit(mDimX) + 1;
+        uint32_t l2y = rsFindHighBit(mDimY) + 1;
+        uint32_t l2z = rsFindHighBit(mDimZ) + 1;
+
+        mLODCount = rsMax(l2x, l2y);
+        mLODCount = rsMax(mLODCount, l2z);
+    } else {
+        mLODCount = 1;
+    }
+    if (mLODCount != oldLODCount) {
+        delete [] mLODs;
+        mLODs = new LOD[mLODCount];
+    }
+
+    //LOGE("xyz %i %i %i", mDimX, mDimY, mDimZ);
+    //LOGE("mips %i", mLODCount);
+    //LOGE("e size %i", mElement->getSizeBytes());
+    uint32_t tx = mDimX;
+    uint32_t ty = mDimY;
+    uint32_t tz = mDimZ;
+    size_t offset = 0;
+    for (uint32_t lod=0; lod < mLODCount; lod++) {
+        mLODs[lod].mX = tx;
+        mLODs[lod].mY = ty;
+        mLODs[lod].mZ = tz;
+        mLODs[lod].mOffset = offset;
+        //LOGE("txyz %i %i %i", tx, ty, tz);
+        offset += tx * rsMax(ty, 1u) * rsMax(tz, 1u) * mElement->getSizeBytes();
+        tx >>= 1;
+        ty >>= 1;
+        tz >>= 1;
+    }
+
+    //LOGE("size %i", offset);
+
+    // At this point the offset is the size of a mipmap chain;
+    mMipChainSizeBytes = offset;
+
+    if (mFaces) {
+        offset *= 6;
+    }
+    mTotalSizeBytes = offset;
+
+}
+
+uint32_t Type::getLODOffset(uint32_t lod, uint32_t x) const
+{
+    uint32_t offset = mLODs[lod].mOffset;
+    offset += x * mElement->getSizeBytes();
+    return offset;
+}
+
+uint32_t Type::getLODOffset(uint32_t lod, uint32_t x, uint32_t y) const
+{
+    uint32_t offset = mLODs[lod].mOffset;
+    offset += (x + y * mLODs[lod].mX) * mElement->getSizeBytes();
+    return offset;
+}
+
+uint32_t Type::getLODOffset(uint32_t lod, uint32_t x, uint32_t y, uint32_t z) const
+{
+    uint32_t offset = mLODs[lod].mOffset;
+    offset += (x + y*mLODs[lod].mX + z*mLODs[lod].mX*mLODs[lod].mY) * mElement->getSizeBytes();
+    return offset;
+}
+
+
+//////////////////////////////////////////////////
+// 
+namespace android {
+namespace renderscript {
+
+void rsi_TypeBegin(Context *rsc, RsElement vse)
+{
+    TypeState * stc = &rsc->mStateType;
+
+    stc->mX = 0;
+    stc->mY = 0;
+    stc->mZ = 0;
+    stc->mLOD = false;
+    stc->mFaces = false;
+    stc->mElement.set(static_cast<const Element *>(vse));
+}
+
+void rsi_TypeAdd(Context *rsc, RsDimension dim, size_t value)
+{
+    TypeState * stc = &rsc->mStateType;
+
+    if (dim < 0) {
+        //error
+        return;
+    }
+
+
+    switch (dim) {
+    case RS_DIMENSION_X:
+        stc->mX = value;
+        return;
+    case RS_DIMENSION_Y:
+        stc->mY = value;
+        return;
+    case RS_DIMENSION_Z:
+        stc->mZ = value;
+        return;
+    case RS_DIMENSION_FACE:
+        stc->mFaces = (value != 0);
+        return;
+    case RS_DIMENSION_LOD:
+        stc->mLOD = (value != 0);
+        return;
+    default:
+        break;
+    }
+
+
+    int32_t arrayNum = dim - RS_DIMENSION_ARRAY_0;
+    if ((dim < 0) || (dim > RS_DIMENSION_MAX)) {
+        LOGE("rsTypeAdd: Bad dimension");
+        //error
+        return;
+    }
+
+    // todo: implement array support
+
+}
+
+RsType rsi_TypeCreate(Context *rsc)
+{
+    TypeState * stc = &rsc->mStateType;
+
+    Type * st = new Type();
+    st->setDimX(stc->mX);
+    st->setDimY(stc->mY);
+    st->setDimZ(stc->mZ);
+    st->setElement(stc->mElement.get());
+    st->setDimLOD(stc->mLOD);
+    st->setDimFaces(stc->mFaces);
+    st->compute();
+
+    stc->mAllTypes.add(st);
+
+    return st;
+}
+
+void rsi_TypeDestroy(Context *rsc, RsType vst)
+{
+    TypeState * stc = &rsc->mStateType;
+    Type * st = static_cast<Type *>(vst);
+
+    for (size_t ct = 0; ct < stc->mAllTypes.size(); ct++) {
+        if (stc->mAllTypes[ct] == st) {
+            stc->mAllTypes.removeAt(ct);
+            break;
+        }
+    }
+    delete st;
+}
+
+}
+}
+
diff --git a/libs/rs/rsType.h b/libs/rs/rsType.h
new file mode 100644
index 0000000..a717893
--- /dev/null
+++ b/libs/rs/rsType.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_STRUCTURED_TYPE_H
+#define ANDROID_STRUCTURED_TYPE_H
+
+#include "rsElement.h"
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+    
+class Type : public ObjectBase
+{
+public:
+    Type();
+    virtual ~Type();
+
+    Type * createTex2D(const Element *, size_t w, size_t h, bool mip);
+
+
+    size_t getOffsetForFace(uint32_t face) const;
+
+    size_t getSizeBytes() const {return mTotalSizeBytes;}
+    size_t getElementSizeBytes() const {return mElement->getSizeBytes();}
+    const Element * getElement() const {return mElement.get();}
+
+    uint32_t getDimX() const {return mDimX;}
+    uint32_t getDimY() const {return mDimY;}
+    uint32_t getDimZ() const {return mDimZ;}
+    uint32_t getDimLOD() const {return mDimLOD;}
+    bool getDimFaces() const {return mFaces;}
+
+    uint32_t getLODDimX(uint32_t lod) const {rsAssert(lod < mLODCount); return mLODs[lod].mX;}
+    uint32_t getLODDimY(uint32_t lod) const {rsAssert(lod < mLODCount); return mLODs[lod].mY;}
+    uint32_t getLODDimZ(uint32_t lod) const {rsAssert(lod < mLODCount); return mLODs[lod].mZ;}
+    uint32_t getLODOffset(uint32_t lod) const {rsAssert(lod < mLODCount); return mLODs[lod].mOffset;}
+
+    uint32_t getLODOffset(uint32_t lod, uint32_t x) const;
+    uint32_t getLODOffset(uint32_t lod, uint32_t x, uint32_t y) const;
+    uint32_t getLODOffset(uint32_t lod, uint32_t x, uint32_t y, uint32_t z) const;
+
+    uint32_t getLODCount() const {return mLODCount;}
+
+
+    void setElement(const Element *e) {mElement.set(e);}
+    void setDimX(uint32_t v) {mDimX = v;}
+    void setDimY(uint32_t v) {mDimY = v;}
+    void setDimZ(uint32_t v) {mDimZ = v;}
+    void setDimFaces(bool v) {mFaces = v;}
+    void setDimLOD(bool v) {mDimLOD = v;}
+
+    void clear();
+    void compute();
+
+
+protected:
+    struct LOD {
+        size_t mX;
+        size_t mY;
+        size_t mZ;
+        size_t mOffset;
+    };
+
+    void makeLODTable();
+
+    // Internal structure from most to least significant.
+    // * Array dimensions
+    // * Faces
+    // * Mipmaps
+    // * xyz
+
+    ObjectBaseRef<const Element> mElement;
+
+    // Size of the structure in the various dimensions.  A missing Dimension is
+    // specified as a 0 and not a 1.
+    size_t mDimX;
+    size_t mDimY;
+    size_t mDimZ;
+    bool mDimLOD;
+    bool mFaces;
+
+    // A list of array dimensions.  The count is the number of array dimensions and the 
+    // sizes is a per array size.
+    //Vector<size_t> mDimArraysSizes;
+
+    // count of mipmap levels, 0 indicates no mipmapping
+
+    size_t mMipChainSizeBytes;
+    size_t mTotalSizeBytes;
+    LOD *mLODs;
+    uint32_t mLODCount;
+
+private:
+    Type(const Type &);
+};
+
+
+class TypeState {
+public:
+    TypeState();
+    ~TypeState();
+
+    Vector<Type *> mAllTypes;
+
+    size_t mX;
+    size_t mY;
+    size_t mZ;
+    uint32_t mLOD;
+    bool mFaces;
+    ObjectBaseRef<const Element> mElement;
+
+
+    
+};
+
+
+}
+}
+#endif //ANDROID_STRUCTURED_TYPE
diff --git a/libs/rs/rsUtils.h b/libs/rs/rsUtils.h
new file mode 100644
index 0000000..683c96e
--- /dev/null
+++ b/libs/rs/rsUtils.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_RS_UTILS_H
+#define ANDROID_RS_UTILS_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <stdlib.h>
+
+namespace android {
+namespace renderscript {
+
+#if 1
+#define rsAssert(v) do {if(!(v)) LOGE("rsAssert failed: %s, in %s at %i", #v, __FILE__, __LINE__);} while(0)
+#else
+#define rsAssert(v) while(0)
+#endif
+
+template<typename T>
+T rsMin(T in1, T in2)
+{
+    if (in1 > in2) {
+        return in2;
+    }
+    return in1;
+}
+
+template<typename T>
+T rsMax(T in1, T in2)
+{
+    if (in1 < in2) {
+        return in2;
+    }
+    return in1;
+}
+
+template<typename T>
+T rsFindHighBit(T val)
+{
+    uint32_t bit = 0;
+    while(val > 1) {
+        bit++;
+        val>>=1;
+    }
+    return bit;
+}
+
+template<typename T>
+bool rsIsPow2(T val)
+{
+    return (val & (val-1)) == 0;
+}
+
+template<typename T>
+T rsHigherPow2(T v)
+{
+    if (rsIsPow2(v)) {
+        return v;
+    }
+    return 1 << (rsFindHighBit(v) + 1);
+}
+
+template<typename T>
+T rsLowerPow2(T v)
+{
+    if (rsIsPow2(v)) {
+        return v;
+    }
+    return 1 << rsFindHighBit(v);
+}
+
+
+static inline uint16_t rs888to565(uint32_t r, uint32_t g, uint32_t b)
+{
+    uint16_t t = 0;
+    t |= r >> 3;
+    t |= (g >> 2) << 5;
+    t |= (b >> 3) << 11;
+    return t;
+}
+
+static inline uint16_t rsBoxFilter565(uint16_t i1, uint16_t i2, uint16_t i3, uint16_t i4)
+{
+    uint32_t r = ((i1 & 0x1f) + (i2 & 0x1f) + (i3 & 0x1f) + (i4 & 0x1f));
+    uint32_t g = ((i1 >> 5) & 0x3f) + ((i2 >> 5) & 0x3f) + ((i3 >> 5) & 0x3f) + ((i1 >> 5) & 0x3f);
+    uint32_t b = ((i1 >> 11) + (i2 >> 11) + (i3 >> 11) + (i4 >> 11));
+    return (r >> 2) | ((g >> 2) << 5) | ((b >> 2) << 11);
+}
+
+
+
+
+
+
+}
+}
+
+#endif //ANDROID_RS_OBJECT_BASE_H
+
+
diff --git a/libs/rs/rsgApi.cpp.rsg b/libs/rs/rsgApi.cpp.rsg
new file mode 100644
index 0000000..0cfbf08
--- /dev/null
+++ b/libs/rs/rsgApi.cpp.rsg
@@ -0,0 +1 @@
+2
diff --git a/libs/rs/rsgApiFuncDecl.h.rsg b/libs/rs/rsgApiFuncDecl.h.rsg
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/libs/rs/rsgApiFuncDecl.h.rsg
@@ -0,0 +1 @@
+1
diff --git a/libs/rs/rsgApiReplay.cpp.rsg b/libs/rs/rsgApiReplay.cpp.rsg
new file mode 100644
index 0000000..00750ed
--- /dev/null
+++ b/libs/rs/rsgApiReplay.cpp.rsg
@@ -0,0 +1 @@
+3
diff --git a/libs/rs/rsgApiStructs.h.rsg b/libs/rs/rsgApiStructs.h.rsg
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/libs/rs/rsgApiStructs.h.rsg
@@ -0,0 +1 @@
+0
diff --git a/libs/rs/rsg_generator.c b/libs/rs/rsg_generator.c
new file mode 100644
index 0000000..a4d659d
--- /dev/null
+++ b/libs/rs/rsg_generator.c
@@ -0,0 +1,291 @@
+
+
+#include "lex.yy.c"
+
+void printFileHeader(FILE *f)
+{
+    fprintf(f, "/*\n");
+    fprintf(f, " * Copyright (C) 2009 The Android Open Source Project\n");
+    fprintf(f, " *\n");
+    fprintf(f, " * Licensed under the Apache License, Version 2.0 (the \"License\");\n");
+    fprintf(f, " * you may not use this file except in compliance with the License.\n");
+    fprintf(f, " * You may obtain a copy of the License at\n");
+    fprintf(f, " *\n");
+    fprintf(f, " *      http://www.apache.org/licenses/LICENSE-2.0\n");
+    fprintf(f, " *\n");
+    fprintf(f, " * Unless required by applicable law or agreed to in writing, software\n");
+    fprintf(f, " * distributed under the License is distributed on an \"AS IS\" BASIS,\n");
+    fprintf(f, " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n");
+    fprintf(f, " * See the License for the specific language governing permissions and\n");
+    fprintf(f, " * limitations under the License.\n");
+    fprintf(f, " */\n\n");
+}
+
+void printVarType(FILE *f, const VarType *vt)
+{
+    int ct;
+    if (vt->isConst) {
+        fprintf(f, "const ");
+    }
+
+    switch(vt->type) {
+    case 0:
+        fprintf(f, "void");
+        break;
+    case 1:
+        fprintf(f, "int%i_t", vt->bits);
+        break;
+    case 2:
+        fprintf(f, "uint%i_t", vt->bits);
+        break;
+    case 3:
+        if (vt->bits == 32)
+            fprintf(f, "float");
+        else
+            fprintf(f, "double");
+        break;
+    case 4:
+        fprintf(f, "%s", vt->typename);
+        break;
+    }
+
+    if(vt->ptrLevel) {
+        fprintf(f, " ");
+        for(ct=0; ct < vt->ptrLevel; ct++) {
+            fprintf(f, "*");
+        }
+    }
+
+    if(vt->name[0]) {
+        fprintf(f, " %s", vt->name);
+    }
+}
+
+void printArgList(FILE *f, const ApiEntry * api, int assumePrevious)
+{
+    int ct;
+    for(ct=0; ct < api->paramCount; ct++) {
+        if (ct || assumePrevious) {
+            fprintf(f, ", ");
+        }
+        printVarType(f, &api->params[ct]);
+    }
+}
+
+void printStructures(FILE *f)
+{
+    int ct;
+    int ct2;
+
+    for(ct=0; ct < apiCount; ct++) {
+        fprintf(f, "typedef struct RS_CMD_%s_rec RS_CMD_%s;\n", apis[ct].name, apis[ct].name);
+    }
+    fprintf(f, "\n");
+
+    for(ct=0; ct < apiCount; ct++) {
+        const ApiEntry * api = &apis[ct];
+        fprintf(f, "#define RS_CMD_ID_%s %i\n", api->name, ct+1);
+        fprintf(f, "struct RS_CMD_%s_rec {\n", api->name);
+        //fprintf(f, "    RsCommandHeader _hdr;\n");
+
+        for(ct2=0; ct2 < api->paramCount; ct2++) {
+            fprintf(f, "    ");
+            printVarType(f, &api->params[ct2]);
+            fprintf(f, ";\n");
+        }
+        fprintf(f, "};\n\n");
+    }
+}
+
+void printFuncDecl(FILE *f, const ApiEntry *api, const char *prefix, int addContext)
+{
+    printVarType(f, &api->ret);
+    fprintf(f, " %s%s (", prefix, api->name);
+    if (addContext) {
+        fprintf(f, "Context *");
+    }
+    printArgList(f, api, addContext);
+    fprintf(f, ")");
+}
+
+void printFuncDecls(FILE *f, const char *prefix, int addContext)
+{
+    int ct;
+    for(ct=0; ct < apiCount; ct++) {
+        printFuncDecl(f, &apis[ct], prefix, addContext);
+        fprintf(f, ";\n");
+    }
+    fprintf(f, "\n\n");
+}
+
+void printPlaybackFuncs(FILE *f, const char *prefix)
+{
+    int ct;
+    for(ct=0; ct < apiCount; ct++) {
+        fprintf(f, "void %s%s (Context *, const void *);\n", prefix, apis[ct].name);
+    }
+}
+
+void printApiCpp(FILE *f)
+{
+    int ct;
+    int ct2;
+
+    fprintf(f, "#include \"rsDevice.h\"\n");
+    fprintf(f, "#include \"rsContext.h\"\n");
+    fprintf(f, "#include \"rsThreadIO.h\"\n");
+    //fprintf(f, "#include \"rsgApiStructs.h\"\n");
+    fprintf(f, "#include \"rsgApiFuncDecl.h\"\n");
+    fprintf(f, "\n");
+    fprintf(f, "using namespace android;\n");
+    fprintf(f, "using namespace android::renderscript;\n");
+    fprintf(f, "\n");
+
+    for(ct=0; ct < apiCount; ct++) {
+        int needFlush = 0;
+        const ApiEntry * api = &apis[ct];
+
+        printFuncDecl(f, api, "rs", 0);
+        fprintf(f, "\n{\n");
+        fprintf(f, "    ThreadIO *io = gIO;\n");
+        //fprintf(f, "    LOGE(\"add command %s\\n\");\n", api->name);
+        fprintf(f, "    RS_CMD_%s *cmd = static_cast<RS_CMD_%s *>(io->mToCore.reserve(sizeof(RS_CMD_%s)));\n", api->name, api->name, api->name);
+        fprintf(f, "    uint32_t size = sizeof(RS_CMD_%s);\n", api->name);
+
+        for(ct2=0; ct2 < api->paramCount; ct2++) {
+            const VarType *vt = &api->params[ct2];
+            needFlush += vt->ptrLevel;
+            fprintf(f, "    cmd->%s = %s;\n", vt->name, vt->name);
+        }
+        if (api->ret.typename[0]) {
+            needFlush = 1;
+        }
+
+        fprintf(f, "    io->mToCore.commit");
+        if (needFlush) {
+            fprintf(f, "Sync");
+        }
+        fprintf(f, "(RS_CMD_ID_%s, size);\n", api->name);
+
+        if (api->ret.typename[0]) {
+            fprintf(f, "    return reinterpret_cast<");
+            printVarType(f, &api->ret);
+            fprintf(f, ">(io->mToCoreRet);\n");
+        }
+        fprintf(f, "};\n\n");
+    }
+}
+
+void printPlaybackCpp(FILE *f)
+{
+    int ct;
+    int ct2;
+
+    fprintf(f, "#include \"rsDevice.h\"\n");
+    fprintf(f, "#include \"rsContext.h\"\n");
+    fprintf(f, "#include \"rsThreadIO.h\"\n");
+    //fprintf(f, "#include \"rsgApiStructs.h\"\n");
+    fprintf(f, "#include \"rsgApiFuncDecl.h\"\n");
+    fprintf(f, "\n");
+    fprintf(f, "namespace android {\n");
+    fprintf(f, "namespace renderscript {\n");
+    fprintf(f, "\n");
+
+    for(ct=0; ct < apiCount; ct++) {
+        const ApiEntry * api = &apis[ct];
+
+        fprintf(f, "void rsp_%s(Context *con, const void *vp)\n", api->name);
+        fprintf(f, "{\n");
+        //fprintf(f, "    LOGE(\"play command %s\\n\");\n", api->name);
+        fprintf(f, "    const RS_CMD_%s *cmd = static_cast<const RS_CMD_%s *>(vp);\n", api->name, api->name);
+        fprintf(f, "    ");
+        if (api->ret.typename[0]) {
+            fprintf(f, "gIO->mToCoreRet = (intptr_t)");
+        }
+        fprintf(f, "rsi_%s(con", api->name);
+        for(ct2=0; ct2 < api->paramCount; ct2++) {
+            const VarType *vt = &api->params[ct2];
+            fprintf(f, ",");
+            fprintf(f, "\n           cmd->%s", vt->name);
+        }
+        fprintf(f, ");\n");
+
+        fprintf(f, "};\n\n");
+    }
+
+    fprintf(f, "RsPlaybackFunc gPlaybackFuncs[] = {\n");
+    fprintf(f, "    NULL,\n");
+    for(ct=0; ct < apiCount; ct++) {
+        fprintf(f, "    %s%s,\n", "rsp_", apis[ct].name);
+    }
+    fprintf(f, "};\n");
+
+    fprintf(f, "};\n");
+    fprintf(f, "};\n");
+}
+
+int main(int argc, char **argv)
+{
+    if (argc != 3) {
+        fprintf(stderr, "usage: %s commandFile outFile\n", argv[0]);
+        return 1;
+    }
+    const char* rsgFile = argv[1];
+    const char* outFile = argv[2];
+    FILE* input = fopen(rsgFile, "r");
+
+    char choice = fgetc(input);
+    fclose(input);
+
+    if (choice < '0' || choice > '3') {
+        fprintf(stderr, "Uknown command: \'%c\'\n", choice);
+        return -2;
+    }
+
+    yylex();
+    // printf("# of lines = %d\n", num_lines);
+
+    FILE *f = fopen(outFile, "w");
+
+    printFileHeader(f);
+    switch(choice) {
+        case '0': // rsgApiStructs.h
+        {
+            fprintf(f, "\n");
+            fprintf(f, "#include \"rsContext.h\"\n");
+            fprintf(f, "\n");
+            fprintf(f, "namespace android {\n");
+            fprintf(f, "namespace renderscript {\n");
+            printStructures(f);
+            printFuncDecls(f, "rsi_", 1);
+            printPlaybackFuncs(f, "rsp_");
+            fprintf(f, "\n\ntypedef void (*RsPlaybackFunc)(Context *, const void *);\n");
+            fprintf(f, "extern RsPlaybackFunc gPlaybackFuncs[];\n");
+
+            fprintf(f, "}\n");
+            fprintf(f, "}\n");
+        }
+        break;
+
+        case '1': // rsgApiFuncDecl.h
+        {
+            printFuncDecls(f, "rs", 0);
+        }
+        break;
+
+        case '2': // rsgApi.cpp
+        {
+            printApiCpp(f);
+        }
+        break;
+
+        case '3': // rsgApiReplay.cpp
+        {
+            printFileHeader(f);
+            printPlaybackCpp(f);
+        }
+        break;
+    }
+    fclose(f);
+    return 0;
+}
diff --git a/libs/rs/spec.lex b/libs/rs/spec.lex
new file mode 100644
index 0000000..0f8e9ab
--- /dev/null
+++ b/libs/rs/spec.lex
@@ -0,0 +1,171 @@
+%option stack
+
+%x comment
+%x api_entry
+%x api_entry2
+%x api_entry_param
+%x var_type
+
+DIGIT    [0-9]
+ID       [a-zA-Z_][a-zA-Z0-9_]*
+
+
+   int num_lines = 0;
+
+   typedef struct {
+      int isConst;
+      int type;
+      int bits;
+      int ptrLevel;
+      char name[256];
+      char typename[256];
+   } VarType;
+
+   VarType *currType = 0;
+
+   typedef struct {
+      char name[256];
+      int sync;
+      int paramCount;
+      VarType ret;
+      VarType params[16];
+   } ApiEntry;
+
+   ApiEntry apis[128];
+   int apiCount = 0;
+
+   int typeNextState;
+
+%%
+
+"/*"         BEGIN(comment);
+<comment>[^*\n]*        /* eat anything that's not a '*' */
+<comment>"*"+[^*/\n]*   /* eat up '*'s not followed by '/'s */
+<comment>\n             ++num_lines;
+<comment>"*"+"/"        BEGIN(INITIAL);
+
+<*>" "   //printf("found ' '\n");
+<*>"\n"  ++num_lines; //printf("found lf \n");
+
+{ID} {
+    memset(&apis[apiCount], 0, sizeof(ApiEntry));
+    memcpy(apis[apiCount].name, yytext, yyleng);
+    BEGIN(api_entry);
+    }
+
+<api_entry>"{" {
+    BEGIN(api_entry2);
+    }
+
+<api_entry2>"sync" {
+    apis[apiCount].sync = 1;
+    }
+
+<api_entry2>"ret" {
+    currType = &apis[apiCount].ret;
+    typeNextState = api_entry2;
+    BEGIN(var_type);
+    }
+
+<api_entry2>"param" {
+    currType = &apis[apiCount].params[apis[apiCount].paramCount];
+    apis[apiCount].paramCount++;
+    typeNextState = api_entry_param;
+    BEGIN(var_type);
+    }
+
+<var_type>"const" {
+    currType->isConst = 1;
+    }
+
+<var_type>"i8" {
+    currType->type = 1;
+    currType->bits = 8;
+    BEGIN(typeNextState);
+    }
+
+<var_type>"i16" {
+    currType->type = 1;
+    currType->bits = 16;
+    BEGIN(typeNextState);
+    }
+
+<var_type>"i32" {
+    currType->type = 1;
+    currType->bits = 32;
+    BEGIN(typeNextState);
+    }
+
+<var_type>"i64" {
+    currType->type = 1;
+    currType->bits = 64;
+    BEGIN(typeNextState);
+    }
+
+<var_type>"u8" {
+    currType->type = 2;
+    currType->bits = 8;
+    BEGIN(typeNextState);
+    }
+
+<var_type>"u16" {
+    currType->type = 2;
+    currType->bits = 16;
+    BEGIN(typeNextState);
+    }
+
+<var_type>"u32" {
+    currType->type = 2;
+    currType->bits = 32;
+    BEGIN(typeNextState);
+    }
+
+<var_type>"u64" {
+    currType->type = 2;
+    currType->bits = 64;
+    BEGIN(typeNextState);
+    }
+
+<var_type>"f" {
+    currType->type = 3;
+    currType->bits = 32;
+    BEGIN(typeNextState);
+    }
+
+<var_type>"d" {
+    currType->type = 3;
+    currType->bits = 64;
+    BEGIN(typeNextState);
+    }
+
+<var_type>{ID} {
+    currType->type = 4;
+    currType->bits = 32;
+    memcpy(currType->typename, yytext, yyleng);
+    BEGIN(typeNextState);
+    }
+
+<api_entry_param>"*" {
+    currType->ptrLevel ++;
+    }
+
+<api_entry_param>{ID} {
+    memcpy(currType->name, yytext, yyleng);
+    BEGIN(api_entry2);
+    }
+
+
+<api_entry2>"}" {
+    apiCount++;
+    BEGIN(INITIAL);
+    }
+
+
+%%
+
+
+int yywrap()
+{
+    return 1;
+}
+
diff --git a/libs/surfaceflinger/Android.mk b/libs/surfaceflinger/Android.mk
index b7a464f..a5698f2 100644
--- a/libs/surfaceflinger/Android.mk
+++ b/libs/surfaceflinger/Android.mk
@@ -6,7 +6,6 @@
     DisplayHardware/DisplayHardware.cpp \
     DisplayHardware/DisplayHardwareBase.cpp \
     GPUHardware/GPUHardware.cpp \
-    BootAnimation.cpp \
     BlurFilter.cpp.arm \
     CPUGauge.cpp \
     Layer.cpp \
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index 37d1dedd..efaf016 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -62,6 +62,13 @@
 #include "GPUHardware/GPUHardware.h"
 
 
+/* ideally AID_GRAPHICS would be in a semi-public header
+ * or there would be a way to map a user/group name to its id
+ */
+#ifndef AID_GRAPHICS
+#define AID_GRAPHICS 1003
+#endif
+
 #define DISPLAY_COUNT       1
 
 namespace android {
@@ -185,7 +192,6 @@
         mDebugCpu(0),
         mDebugFps(0),
         mDebugBackground(0),
-        mDebugNoBootAnimation(0),
         mSyncObject(),
         mDeplayedTransactionPending(0),
         mConsoleSignals(0),
@@ -208,14 +214,11 @@
     mDebugBackground = atoi(value);
     property_get("debug.sf.showfps", value, "0");
     mDebugFps = atoi(value);
-    property_get("debug.sf.nobootanimation", value, "0");
-    mDebugNoBootAnimation = atoi(value);
 
     LOGI_IF(mDebugRegion,           "showupdates enabled");
     LOGI_IF(mDebugCpu,              "showcpu enabled");
     LOGI_IF(mDebugBackground,       "showbackground enabled");
     LOGI_IF(mDebugFps,              "showfps enabled");
-    LOGI_IF(mDebugNoBootAnimation,  "boot animation disabled");
 }
 
 SurfaceFlinger::~SurfaceFlinger()
@@ -325,11 +328,8 @@
 {
     const nsecs_t now = systemTime();
     const nsecs_t duration = now - mBootTime;
-    LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );
-    if (mBootAnimation != 0) {
-        mBootAnimation->requestExit();
-        mBootAnimation.clear();
-    }
+    LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );  
+    property_set("ctl.stop", "bootanim");
 }
 
 void SurfaceFlinger::onFirstRef()
@@ -457,10 +457,10 @@
     if (mDebugCpu)
         mCpuGauge = new CPUGauge(this, ms2ns(500));
 
-    // the boot animation!
-    if (mDebugNoBootAnimation == false)
-        mBootAnimation = new BootAnimation(this);
-
+    
+    // start boot animation
+    property_set("ctl.start", "bootanim");
+    
     return NO_ERROR;
 }
 
@@ -1544,13 +1544,13 @@
             // codes that require permission check
             IPCThreadState* ipc = IPCThreadState::self();
             const int pid = ipc->getCallingPid();
+            const int uid = ipc->getCallingUid();
             const int self_pid = getpid();
-            if (UNLIKELY(pid != self_pid)) {
+            if (UNLIKELY(pid != self_pid && uid != AID_GRAPHICS)) {
                 // we're called from a different process, do the real check
                 if (!checkCallingPermission(
                         String16("android.permission.ACCESS_SURFACE_FLINGER")))
                 {
-                    const int uid = ipc->getCallingUid();
                     LOGE("Permission Denial: "
                             "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
                     return PERMISSION_DENIED;
diff --git a/libs/surfaceflinger/SurfaceFlinger.h b/libs/surfaceflinger/SurfaceFlinger.h
index 927908d4..126bce8 100644
--- a/libs/surfaceflinger/SurfaceFlinger.h
+++ b/libs/surfaceflinger/SurfaceFlinger.h
@@ -36,7 +36,6 @@
 #include <private/ui/SurfaceFlingerSynchro.h>
 
 #include "Barrier.h"
-#include "BootAnimation.h"
 #include "CPUGauge.h"
 #include "Layer.h"
 #include "Tokenizer.h"
@@ -347,7 +346,6 @@
                 sp<SurfaceHeapManager>      mSurfaceHeapManager;
                 sp<GPUHardwareInterface>    mGPU;
                 GLuint                      mWormholeTexName;
-                sp<BootAnimation>           mBootAnimation;
                 nsecs_t                     mBootTime;
                 
                 // Can only accessed from the main thread, these members
@@ -374,7 +372,6 @@
                 int                         mDebugCpu;
                 int                         mDebugFps;
                 int                         mDebugBackground;
-                int                         mDebugNoBootAnimation;
 
                 // these are thread safe
     mutable     Barrier                     mReadyToRunBarrier;
diff --git a/libs/surfaceflinger/VRamHeap.cpp b/libs/surfaceflinger/VRamHeap.cpp
index 7132d0d..68c0a5e 100644
--- a/libs/surfaceflinger/VRamHeap.cpp
+++ b/libs/surfaceflinger/VRamHeap.cpp
@@ -35,6 +35,8 @@
 #include <binder/MemoryHeapPmem.h>
 #include <binder/MemoryHeapBase.h>
 
+#include <EGL/eglnatives.h>
+
 #include "GPUHardware/GPUHardware.h"
 #include "SurfaceFlinger.h"
 #include "VRamHeap.h"
diff --git a/libs/ui/ISurfaceFlingerClient.cpp b/libs/ui/ISurfaceFlingerClient.cpp
index 69731ab..a93ae67 100644
--- a/libs/ui/ISurfaceFlingerClient.cpp
+++ b/libs/ui/ISurfaceFlingerClient.cpp
@@ -35,6 +35,13 @@
 
 // ---------------------------------------------------------------------------
 
+/* ideally AID_GRAPHICS would be in a semi-public header
+ * or there would be a way to map a user/group name to its id
+ */
+#ifndef AID_GRAPHICS
+#define AID_GRAPHICS 1003
+#endif
+
 #define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
 #define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
 
@@ -136,13 +143,13 @@
      
      IPCThreadState* ipc = IPCThreadState::self();
      const int pid = ipc->getCallingPid();
-     const int self_pid    = getpid();
-     if (UNLIKELY(pid != self_pid)) {
+     const int uid = ipc->getCallingUid();
+     const int self_pid = getpid();
+     if (UNLIKELY(pid != self_pid && uid != AID_GRAPHICS)) {
          // we're called from a different process, do the real check
          if (!checkCallingPermission(
                  String16("android.permission.ACCESS_SURFACE_FLINGER")))
          {
-             const int uid = ipc->getCallingUid();
              LOGE("Permission Denial: "
                      "can't openGlobalTransaction pid=%d, uid=%d", pid, uid);
              return PERMISSION_DENIED;
diff --git a/libs/ui/Overlay.cpp b/libs/ui/Overlay.cpp
index 9fae416..a092f8d 100644
--- a/libs/ui/Overlay.cpp
+++ b/libs/ui/Overlay.cpp
@@ -129,12 +129,8 @@
 OverlayRef::~OverlayRef()
 {
     if (mOwnHandle) {
-        /* FIXME: handles should be promoted to "real" API and be handled by 
-         * the framework */
-        for (int i=0 ; i<mOverlayHandle->numFds ; i++) {
-            close(mOverlayHandle->data[i]);
-        }
-        free((void*)mOverlayHandle);
+        native_handle_close(mOverlayHandle);
+        native_handle_delete(const_cast<native_handle*>(mOverlayHandle));
     }
 }
 
@@ -147,7 +143,7 @@
         uint32_t f = data.readInt32();
         uint32_t ws = data.readInt32();
         uint32_t hs = data.readInt32();
-        native_handle* handle = data.readNativeHandle(NULL, NULL);
+        native_handle* handle = data.readNativeHandle();
 
         result = new OverlayRef();
         result->mOverlayHandle = handle;
@@ -169,7 +165,7 @@
         reply->writeInt32(o->mFormat);
         reply->writeInt32(o->mWidthStride);
         reply->writeInt32(o->mHeightStride);
-        reply->writeNativeHandle(*(o->mOverlayHandle));
+        reply->writeNativeHandle(o->mOverlayHandle);
     } else {
         reply->writeStrongBinder(NULL);
     }
diff --git a/libs/utils/backup_helper_file.cpp b/libs/utils/backup_helper_file.cpp
index 8efb3eb..7ec2ce8 100644
--- a/libs/utils/backup_helper_file.cpp
+++ b/libs/utils/backup_helper_file.cpp
@@ -26,6 +26,7 @@
 #include <sys/types.h>
 #include <sys/uio.h>
 #include <sys/stat.h>
+#include <sys/time.h>  // for utimes
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
@@ -607,14 +608,14 @@
         0x11, 0x00, 0x00, 0x00,  0x62, 0x79, 0x74, 0x65,
         0x73, 0x5f, 0x6f, 0x66,  0x5f, 0x70, 0x61, 0x64,
         0x64, 0x69, 0x6e, 0x67,  0x33, 0xab, 0xab, 0xab,
-        
+
         // bytes of padding2
         0x44, 0x11, 0x22, 0x33,  0xef, 0xbe, 0xad, 0xde,
         0x44, 0x33, 0x22, 0x11,  0x34, 0x23, 0x12, 0x01,
         0x12, 0x00, 0x00, 0x00,  0x62, 0x79, 0x74, 0x65,
         0x73, 0x5f, 0x6f, 0x66,  0x5f, 0x70, 0x61, 0x64,
         0x64, 0x69, 0x6e, 0x67,  0x5f, 0x32, 0xab, 0xab,
-        
+
         // bytes of padding3
         0x44, 0x11, 0x22, 0x33,  0xef, 0xbe, 0xad, 0xde,
         0x44, 0x33, 0x22, 0x11,  0x34, 0x23, 0x12, 0x01,
@@ -627,7 +628,7 @@
     if (err != 0) {
         return err;
     }
-    
+
     // read
     fd = open(filename, O_RDONLY);
     if (fd == -1) {
@@ -665,7 +666,7 @@
             matched = false;
         }
     }
-    
+
     return matched ? 0 : 1;
 }
 
@@ -746,7 +747,7 @@
     system("rm -r " SCRATCH_DIR);
     mkdir(SCRATCH_DIR, 0777);
     mkdir(SCRATCH_DIR "data", 0777);
-    
+
     fd = creat(filename, 0666);
     if (fd == -1) {
         fprintf(stderr, "error creating: %s\n", strerror(errno));
@@ -863,7 +864,7 @@
     system("rm -r " SCRATCH_DIR);
     mkdir(SCRATCH_DIR, 0777);
     mkdir(SCRATCH_DIR "data", 0777);
-    
+
     fd = creat(filename, 0666);
     if (fd == -1) {
         fprintf(stderr, "error creating: %s\n", strerror(errno));
@@ -940,9 +941,23 @@
         return errno;
     }
     times[0].tv_sec = st.st_atime;
-    times[0].tv_usec = st.st_atime_nsec / 1000;
     times[1].tv_sec = st.st_mtime;
+
+    // If st_atime is a macro then struct stat64 uses struct timespec
+    // to store the access and modif time values and typically
+    // st_*time_nsec is not defined. In glibc, this is controlled by
+    // __USE_MISC.
+#ifdef __USE_MISC
+#if !defined(st_atime) || defined(st_atime_nsec)
+#error "Check if this __USE_MISC conditional is still needed."
+#endif
+    times[0].tv_usec = st.st_atim.tv_nsec / 1000;
+    times[1].tv_usec = st.st_mtim.tv_nsec / 1000;
+#else
+    times[0].tv_usec = st.st_atime_nsec / 1000;
     times[1].tv_usec = st.st_mtime_nsec / 1000;
+#endif
+
     return 0;
 }
 
@@ -987,7 +1002,7 @@
 
     {
         BackupDataWriter dataStream(dataStreamFD);
-    
+
         err = back_up_files(-1, &dataStream, newSnapshotFD, SCRATCH_DIR, files_before, 5);
         if (err != 0) {
             return err;
@@ -1017,7 +1032,7 @@
     utimes(SCRATCH_DIR "data/e", e_times);
     write_text_file(SCRATCH_DIR "data/g", "g\ngg\n");
     unlink(SCRATCH_DIR "data/f");
-    
+
     char const* files_after[] = {
         "data/a", // added
         "data/b", // same
@@ -1047,7 +1062,7 @@
 
     {
         BackupDataWriter dataStream(dataStreamFD);
-    
+
         err = back_up_files(oldSnapshotFD, &dataStream, newSnapshotFD, SCRATCH_DIR,
                 files_after, 6);
         if (err != 0) {
@@ -1058,7 +1073,7 @@
     close(oldSnapshotFD);
     close(dataStreamFD);
     close(newSnapshotFD);
-    
+
     return 0;
 }
 
diff --git a/libs/utils/futex_synchro.c b/libs/utils/futex_synchro.c
index ba19520..ab48c69 100644
--- a/libs/utils/futex_synchro.c
+++ b/libs/utils/futex_synchro.c
@@ -28,6 +28,7 @@
 // This futex glue code is need on desktop linux, but is already part of bionic.
 #if !defined(HAVE_FUTEX_WRAPPERS)
 
+#include <unistd.h>
 #include <sys/syscall.h>
 typedef unsigned int u32;
 #define asmlinkage
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 3346bed..4d1535f9 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -88,7 +88,7 @@
     private static final int AUDIORECORD_ERROR_SETUP_ZEROFRAMECOUNT      = -16;
     private static final int AUDIORECORD_ERROR_SETUP_INVALIDCHANNELCOUNT = -17;
     private static final int AUDIORECORD_ERROR_SETUP_INVALIDFORMAT       = -18;
-    private static final int AUDIORECORD_ERROR_SETUP_INVALIDSTREAMTYPE   = -19;
+    private static final int AUDIORECORD_ERROR_SETUP_INVALIDSOURCE       = -19;
     private static final int AUDIORECORD_ERROR_SETUP_NATIVEINITFAILED    = -20;
     
     // Events:
@@ -113,13 +113,7 @@
      */
     @SuppressWarnings("unused")
     private int mNativeRecorderInJavaObj;
-    /** 
-     * Accessed by native methods: provides access to record source constants 
-     */
-    @SuppressWarnings("unused")
-    private final static int SOURCE_DEFAULT = MediaRecorder.AudioSource.DEFAULT;
-    @SuppressWarnings("unused")
-    private final static int SOURCE_MIC = MediaRecorder.AudioSource.MIC;
+
     /** 
      * Accessed by native methods: provides access to the callback data.
      */
@@ -252,8 +246,8 @@
 
         //--------------
         // audio source
-        if ( (audioSource != MediaRecorder.AudioSource.DEFAULT)
-                && (audioSource != MediaRecorder.AudioSource.MIC) ) {
+        if ( (audioSource < MediaRecorder.AudioSource.DEFAULT) ||
+             (audioSource > MediaRecorder.getAudioSourceMax()) )  {
             throw (new IllegalArgumentException("Invalid audio source."));
         } else {
             mRecordSource = audioSource;
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 5d90e62..44f21c8 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -125,6 +125,15 @@
         public static final int DEFAULT = 0;
         /** Microphone audio source */
         public static final int MIC = 1;
+
+        /** Voice call uplink (Tx) audio source */
+        public static final int VOICE_UPLINK = 2;
+
+        /** Voice call downlink (Rx) audio source */
+        public static final int VOICE_DOWNLINK = 3;
+
+        /** Voice call uplink + downlink audio source */
+        public static final int VOICE_CALL = 4;
     }
 
     /**
@@ -203,6 +212,12 @@
             throws IllegalStateException;
 
     /**
+     * Gets the maximum value for audio sources.
+     * @see android.media.MediaRecorder.AudioSource
+     */
+    public static final int getAudioSourceMax() { return AudioSource.VOICE_CALL; }
+
+    /**
      * Sets the video source to be used for recording. If this method is not
      * called, the output file will not contain an video track. The source needs
      * to be specified before setting recording-parameters or encoders. Call
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index cac65d6..7561af1 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -177,7 +177,7 @@
 android_media_MediaRecorder_setAudioSource(JNIEnv *env, jobject thiz, jint as)
 {
     LOGV("setAudioSource(%d)", as);
-    if (as < AUDIO_SOURCE_DEFAULT || as > AUDIO_SOURCE_MIC) {
+    if (as < AUDIO_SOURCE_DEFAULT || as > AUDIO_SOURCE_MAX) {
         jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid audio source");
         return;
     }
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 793bbf4..cf0965e 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -50,7 +50,7 @@
 }
 
 AudioRecord::AudioRecord(
-        int streamType,
+        int inputSource,
         uint32_t sampleRate,
         int format,
         int channelCount,
@@ -61,7 +61,7 @@
         int notificationFrames)
     : mStatus(NO_INIT)
 {
-    mStatus = set(streamType, sampleRate, format, channelCount,
+    mStatus = set(inputSource, sampleRate, format, channelCount,
             frameCount, flags, cbf, user, notificationFrames);
 }
 
@@ -82,7 +82,7 @@
 }
 
 status_t AudioRecord::set(
-        int streamType,
+        int inputSource,
         uint32_t sampleRate,
         int format,
         int channelCount,
@@ -104,8 +104,8 @@
         return NO_INIT;
     }
 
-    if (streamType == DEFAULT_INPUT) {
-        streamType = MIC_INPUT;
+    if (inputSource == DEFAULT_INPUT) {
+        inputSource = MIC_INPUT;
     }
 
     if (sampleRate == 0) {
@@ -157,7 +157,7 @@
 
     // open record channel
     status_t status;
-    sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), streamType,
+    sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), inputSource,
                                                        sampleRate, format,
                                                        channelCount,
                                                        frameCount,
@@ -201,6 +201,7 @@
     mMarkerReached = false;
     mNewPosition = 0;
     mUpdatePeriod = 0;
+    mInputSource = (uint8_t)inputSource;
 
     return NO_ERROR;
 }
@@ -242,6 +243,11 @@
     return channelCount()*((format() == AudioSystem::PCM_8_BIT) ? sizeof(uint8_t) : sizeof(int16_t));
 }
 
+int AudioRecord::inputSource() const
+{
+    return (int)mInputSource;
+}
+
 // -------------------------------------------------------------------------
 
 status_t AudioRecord::start()
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index 7395885..09f1c36 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -99,7 +99,7 @@
 
     virtual sp<IAudioRecord> openRecord(
                                 pid_t pid,
-                                int streamType,
+                                int inputSource,
                                 uint32_t sampleRate,
                                 int format,
                                 int channelCount,
@@ -110,7 +110,7 @@
         Parcel data, reply;
         data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
         data.writeInt32(pid);
-        data.writeInt32(streamType);
+        data.writeInt32(inputSource);
         data.writeInt32(sampleRate);
         data.writeInt32(format);
         data.writeInt32(channelCount);
@@ -384,14 +384,14 @@
         case OPEN_RECORD: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
             pid_t pid = data.readInt32();
-            int streamType = data.readInt32();
+            int inputSource = data.readInt32();
             uint32_t sampleRate = data.readInt32();
             int format = data.readInt32();
             int channelCount = data.readInt32();
             size_t bufferCount = data.readInt32();
             uint32_t flags = data.readInt32();
             status_t status;
-            sp<IAudioRecord> record = openRecord(pid, streamType,
+            sp<IAudioRecord> record = openRecord(pid, inputSource,
                     sampleRate, format, channelCount, bufferCount, flags, &status);
             reply->writeInt32(status);
             reply->writeStrongBinder(record->asBinder());
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 1cfe002..a1866be 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -2154,16 +2154,9 @@
             String path = scanFile.getPath();
             if (scanFileNewer) {
                 Log.i(TAG, path + " changed; unpacking");
-                try {
-                    cachePackageSharedLibsLI(pkg, dataPath, scanFile);
-                } catch (IOException e) {
-                    Log.e(TAG, "Failure extracting shared libs", e);
-                    if(mInstaller != null) {
-                        mInstaller.remove(pkgName);
-                    } else {
-                        dataPath.delete();
-                    }
-                    mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+                int err = cachePackageSharedLibsLI(pkg, dataPath, scanFile);
+                if (err != PackageManager.INSTALL_SUCCEEDED) {
+                    mLastScanError = err;
                     return null;
                 }
             }
@@ -2447,14 +2440,15 @@
         return pkg;
     }
 
-    private void cachePackageSharedLibsLI(PackageParser.Package pkg,
-            File dataPath, File scanFile) throws IOException {
+    private int cachePackageSharedLibsLI(PackageParser.Package pkg,
+            File dataPath, File scanFile) {
         File sharedLibraryDir = new File(dataPath.getPath() + "/lib");
-        final String sharedLibraryABI = "armeabi";
+        final String sharedLibraryABI = Build.CPU_ABI;
         final String apkLibraryDirectory = "lib/" + sharedLibraryABI + "/";
         final String apkSharedLibraryPrefix = apkLibraryDirectory + "lib";
         final String sharedLibrarySuffix = ".so";
-        boolean createdSharedLib = false;
+        boolean hasNativeCode = false;
+        boolean installedNativeCode = false;
         try {
             ZipFile zipFile = new ZipFile(scanFile);
             Enumeration<ZipEntry> entries =
@@ -2463,9 +2457,15 @@
             while (entries.hasMoreElements()) {
                 ZipEntry entry = entries.nextElement();
                 if (entry.isDirectory()) {
+                    if (!hasNativeCode && entry.getName().startsWith("lib")) {
+                        hasNativeCode = true;
+                    }
                     continue;
                 }
                 String entryName = entry.getName();
+                if (entryName.startsWith("lib/")) {
+                    hasNativeCode = true;
+                }
                 if (! (entryName.startsWith(apkSharedLibraryPrefix)
                         && entryName.endsWith(sharedLibrarySuffix))) {
                     continue;
@@ -2476,6 +2476,9 @@
                         || (!FileUtils.isFilenameSafe(new File(libFileName)))) {
                     continue;
                 }
+                
+                installedNativeCode = true;
+                
                 String sharedLibraryFilePath = sharedLibraryDir.getPath() +
                     File.separator + libFileName;
                 File sharedLibraryFile = new File(sharedLibraryFilePath);
@@ -2487,19 +2490,23 @@
                     }
                     if (mInstaller == null) {
                         sharedLibraryDir.mkdir();
-                        createdSharedLib = true;
                     }
                     cacheSharedLibLI(pkg, zipFile, entry, sharedLibraryDir,
                             sharedLibraryFile);
                 }
             }
         } catch (IOException e) {
-            Log.e(TAG, "Failed to cache package shared libs", e);
-            if(createdSharedLib) {
-                sharedLibraryDir.delete();
-            }
-            throw e;
+            Log.w(TAG, "Failed to cache package shared libs", e);
+            return PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
         }
+        
+        if (hasNativeCode && !installedNativeCode) {
+            Log.w(TAG, "Install failed: .apk has native code but none for arch "
+                    + Build.CPU_ABI);
+            return PackageManager.INSTALL_FAILED_CPU_ABI_INCOMPATIBLE;
+        }
+        
+        return PackageManager.INSTALL_SUCCEEDED;
     }
 
     private void cacheSharedLibLI(PackageParser.Package pkg,
diff --git a/services/java/com/android/server/SensorService.java b/services/java/com/android/server/SensorService.java
index b2530383f..ceef39f 100644
--- a/services/java/com/android/server/SensorService.java
+++ b/services/java/com/android/server/SensorService.java
@@ -19,7 +19,7 @@
 import android.content.Context;
 import android.hardware.ISensorService;
 import android.os.Binder;
-import android.os.ParcelFileDescriptor;
+import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.IBinder;
 import android.util.Config;
@@ -101,7 +101,7 @@
         _sensors_control_init();
     }
     
-    public ParcelFileDescriptor getDataChanel() throws RemoteException {
+    public Bundle getDataChannel() throws RemoteException {
         return _sensors_control_open();
     }
     
@@ -190,7 +190,7 @@
     ArrayList<Listener> mListeners = new ArrayList<Listener>();
 
     private static native int _sensors_control_init();
-    private static native ParcelFileDescriptor _sensors_control_open();
+    private static native Bundle _sensors_control_open();
     private static native boolean _sensors_control_activate(int sensor, boolean activate);
     private static native int _sensors_control_set_delay(int ms);
     private static native int _sensors_control_wake();
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 5fa8701..64d1ba2 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -1360,14 +1360,17 @@
      * Set the number of radio frequency channels that are allowed to be used
      * in the current regulatory domain. This method should be used only
      * if the correct number of channels cannot be determined automatically
-     * for some reason. If the operation is successful, the new value is
+     * for some reason. If the operation is successful, the new value may be
      * persisted as a Secure setting.
      * @param numChannels the number of allowed channels. Must be greater than 0
      * and less than or equal to 16.
+     * @param persist {@code true} if the setting should be remembered.
      * @return {@code true} if the operation succeeds, {@code false} otherwise, e.g.,
      * {@code numChannels} is outside the valid range.
      */
-    public boolean setNumAllowedChannels(int numChannels) {
+    public boolean setNumAllowedChannels(int numChannels, boolean persist) {
+        Log.i(TAG, "WifiService trying to setNumAllowed to "+numChannels+
+                " with persist set to "+persist);
         enforceChangePermission();
         /*
          * Validate the argument. We'd like to let the Wi-Fi driver do this,
@@ -1386,9 +1389,11 @@
             return false;
         }
 
-        Settings.Secure.putInt(mContext.getContentResolver(),
-                               Settings.Secure.WIFI_NUM_ALLOWED_CHANNELS,
-                               numChannels);
+        if (persist) {
+            Settings.Secure.putInt(mContext.getContentResolver(),
+                                   Settings.Secure.WIFI_NUM_ALLOWED_CHANNELS,
+                                   numChannels);
+        }
         mWifiStateTracker.setNumAllowedChannels(numChannels);
         return true;
     }
diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java
index a695eba..9a4b642 100644
--- a/services/java/com/android/server/am/BatteryStatsService.java
+++ b/services/java/com/android/server/am/BatteryStatsService.java
@@ -206,6 +206,34 @@
         }
     }
 
+    public void noteStartAudio(int uid) {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteAudioOnLocked(uid);
+        }
+    }
+
+    public void noteStopAudio(int uid) {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteAudioOffLocked(uid);
+        }
+    }
+
+    public void noteStartVideo(int uid) {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteVideoOnLocked(uid);
+        }
+    }
+
+    public void noteStopVideo(int uid) {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteVideoOffLocked(uid);
+        }
+    }
+
     public void noteWifiRunning() {
         enforceCallingPermission();
         synchronized (mStats) {
diff --git a/services/jni/com_android_server_SensorService.cpp b/services/jni/com_android_server_SensorService.cpp
index 695a8a3..7390786 100644
--- a/services/jni/com_android_server_SensorService.cpp
+++ b/services/jni/com_android_server_SensorService.cpp
@@ -14,7 +14,10 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "Sensors"
+#define LOG_TAG "SensorService"
+
+#define LOG_NDEBUG 0
+#include "utils/Log.h"
 
 #include <hardware/sensors.h>
 
@@ -36,6 +39,14 @@
     jmethodID mConstructor;
 } gParcelFileDescriptorOffsets;
 
+static struct bundle_descriptor_offsets_t
+{
+    jclass mClass;
+    jmethodID mConstructor;
+    jmethodID mPutIntArray;
+    jmethodID mPutParcelableArray;
+} gBundleOffsets;
+
 /*
  * The method below are not thread-safe and not intended to be 
  */
@@ -59,21 +70,45 @@
 static jobject
 android_open(JNIEnv *env, jclass clazz)
 {
-    int fd = sSensorDevice->open_data_source(sSensorDevice);
-    // new FileDescriptor()
-    jobject filedescriptor = env->NewObject(
-            gFileDescriptorOffsets.mClass, 
-            gFileDescriptorOffsets.mConstructor);
-    
-    if (filedescriptor != NULL) {
-        env->SetIntField(filedescriptor, gFileDescriptorOffsets.mDescriptor, fd);
-        // new ParcelFileDescriptor()
-        return env->NewObject(gParcelFileDescriptorOffsets.mClass,
-                gParcelFileDescriptorOffsets.mConstructor, 
-                filedescriptor);
+    native_handle_t* handle = sSensorDevice->open_data_source(sSensorDevice);
+    if (!handle) {
+        return NULL;
     }
-    close(fd);
-    return NULL;
+
+    // new Bundle()
+    jobject bundle = env->NewObject(
+            gBundleOffsets.mClass,
+            gBundleOffsets.mConstructor);
+
+    if (handle->numFds > 0) {
+        jobjectArray fdArray = env->NewObjectArray(handle->numFds,
+                gParcelFileDescriptorOffsets.mClass, NULL);
+        for (int i = 0; i < handle->numFds; i++) {
+            // new FileDescriptor()
+            jobject fd = env->NewObject(gFileDescriptorOffsets.mClass,
+                    gFileDescriptorOffsets.mConstructor);
+            env->SetIntField(fd, gFileDescriptorOffsets.mDescriptor, handle->data[i]);
+            // new ParcelFileDescriptor()
+            jobject pfd = env->NewObject(gParcelFileDescriptorOffsets.mClass,
+                    gParcelFileDescriptorOffsets.mConstructor, fd);
+            env->SetObjectArrayElement(fdArray, i, pfd);
+        }
+        // bundle.putParcelableArray("fds", fdArray);
+        env->CallVoidMethod(bundle, gBundleOffsets.mPutParcelableArray,
+                env->NewStringUTF("fds"), fdArray);
+    }
+
+    if (handle->numInts > 0) {
+        jintArray intArray = env->NewIntArray(handle->numInts);
+        env->SetIntArrayRegion(intArray, 0, handle->numInts, &handle->data[handle->numInts]);
+        // bundle.putIntArray("ints", intArray);
+        env->CallVoidMethod(bundle, gBundleOffsets.mPutIntArray,
+                env->NewStringUTF("ints"), intArray);
+    }
+
+    // delete the file handle, but don't close any file descriptors
+    native_handle_delete(handle);
+    return bundle;
 }
 
 static jboolean
@@ -99,7 +134,7 @@
 
 static JNINativeMethod gMethods[] = {
     {"_sensors_control_init",     "()I",   (void*) android_init },
-    {"_sensors_control_open",     "()Landroid/os/ParcelFileDescriptor;",  (void*) android_open },
+    {"_sensors_control_open",     "()Landroid/os/Bundle;",  (void*) android_open },
     {"_sensors_control_activate", "(IZ)Z", (void*) android_activate },
     {"_sensors_control_wake",     "()I", (void*) android_data_wake },
     {"_sensors_control_set_delay","(I)I", (void*) android_set_delay },
@@ -116,7 +151,15 @@
 
     clazz = env->FindClass("android/os/ParcelFileDescriptor");
     gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
-    gParcelFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "<init>", "(Ljava/io/FileDescriptor;)V");
+    gParcelFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "<init>",
+            "(Ljava/io/FileDescriptor;)V");
+
+    clazz = env->FindClass("android/os/Bundle");
+    gBundleOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
+    gBundleOffsets.mConstructor = env->GetMethodID(clazz, "<init>", "()V");
+    gBundleOffsets.mPutIntArray = env->GetMethodID(clazz, "putIntArray", "(Ljava/lang/String;[I)V");
+    gBundleOffsets.mPutParcelableArray = env->GetMethodID(clazz, "putParcelableArray",
+            "(Ljava/lang/String;[Landroid/os/Parcelable;)V");
 
     return jniRegisterNativeMethods(env, "com/android/server/SensorService",
             gMethods, NELEM(gMethods));
diff --git a/telephony/java/com/android/internal/telephony/PhoneBase.java b/telephony/java/com/android/internal/telephony/PhoneBase.java
index 7234aa3..2849988 100644
--- a/telephony/java/com/android/internal/telephony/PhoneBase.java
+++ b/telephony/java/com/android/internal/telephony/PhoneBase.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.SharedPreferences;
+import android.net.wifi.WifiManager;
 import android.os.AsyncResult;
 import android.os.Handler;
 import android.os.Looper;
@@ -28,6 +29,7 @@
 import android.os.RegistrantList;
 import android.os.SystemProperties;
 import android.preference.PreferenceManager;
+import android.provider.Settings;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.text.TextUtils;
@@ -194,7 +196,7 @@
         this.mContext = context;
         mLooper = Looper.myLooper();
 
-        setLocaleByCarrier();
+        setPropertiesByCarrier();
 
         setUnitTestMode(unitTestMode);
 
@@ -489,10 +491,10 @@
     }
 
     /**
-     * Set the locale by matching the carrier string in
+     * Set the properties by matching the carrier string in
      * a string-array resource
      */
-    private void setLocaleByCarrier() {
+    private void setPropertiesByCarrier() {
         String carrier = SystemProperties.get("ro.carrier");
 
         if (null == carrier || 0 == carrier.length()) {
@@ -500,18 +502,36 @@
         }
 
         CharSequence[] carrierLocales = mContext.
-                getResources().getTextArray(R.array.carrier_locales);
+                getResources().getTextArray(R.array.carrier_properties);
 
-        for (int i = 0; i < carrierLocales.length-1; i+=2) {
+        for (int i = 0; i < carrierLocales.length; i+=3) {
             String c = carrierLocales[i].toString();
-            String l = carrierLocales[i+1].toString();
             if (carrier.equals(c)) {
+                String l = carrierLocales[i+1].toString();
+                int wifiChannels = 0;
+                try {
+                    wifiChannels = Integer.parseInt(
+                            carrierLocales[i+2].toString());
+                } catch (NumberFormatException e) { }
+
                 String language = l.substring(0, 2);
                 String country = "";
                 if (l.length() >=5) {
                     country = l.substring(3, 5);
                 }
                 setSystemLocale(language, country);
+
+                if (wifiChannels != 0) {
+                    try {
+                        Settings.Secure.getInt(mContext.getContentResolver(),
+                                Settings.Secure.WIFI_NUM_ALLOWED_CHANNELS);
+                    } catch (Settings.SettingNotFoundException e) {
+                        // note this is not persisting
+                        WifiManager wM = (WifiManager)
+                                mContext.getSystemService(Context.WIFI_SERVICE);
+                        wM.setNumAllowedChannels(wifiChannels, false);
+                    }
+                }
                 return;
             }
         }
diff --git a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
index 5112ba0..bdcf3f7 100644
--- a/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -156,6 +156,9 @@
 
     }
 
+    public boolean getDesiredPowerState() {
+        return mDesiredPowerState;
+    }
 
     /**
      * Registration point for combined roaming on
diff --git a/telephony/java/com/android/internal/telephony/SmsHeader.java b/telephony/java/com/android/internal/telephony/SmsHeader.java
index d220648..7872eec 100644
--- a/telephony/java/com/android/internal/telephony/SmsHeader.java
+++ b/telephony/java/com/android/internal/telephony/SmsHeader.java
@@ -111,7 +111,10 @@
             /**
              * NOTE: as defined in the spec, ConcatRef and PortAddr
              * fields should not reoccur, but if they do the last
-             * occurrence is to be used.
+             * occurrence is to be used.  Also, for ConcatRef
+             * elements, if the count is zero, sequence is zero, or
+             * sequence is larger than count, the entire element is to
+             * be ignored.
              */
             int id = inStream.read();
             int length = inStream.read();
@@ -124,7 +127,10 @@
                 concatRef.msgCount = inStream.read();
                 concatRef.seqNumber = inStream.read();
                 concatRef.isEightBits = true;
-                smsHeader.concatRef = concatRef;
+                if (concatRef.msgCount != 0 && concatRef.seqNumber != 0 &&
+                        concatRef.seqNumber <= concatRef.msgCount) {
+                    smsHeader.concatRef = concatRef;
+                }
                 break;
             case ELT_ID_CONCATENATED_16_BIT_REFERENCE:
                 concatRef = new ConcatRef();
@@ -132,7 +138,10 @@
                 concatRef.msgCount = inStream.read();
                 concatRef.seqNumber = inStream.read();
                 concatRef.isEightBits = false;
-                smsHeader.concatRef = concatRef;
+                if (concatRef.msgCount != 0 && concatRef.seqNumber != 0 &&
+                        concatRef.seqNumber <= concatRef.msgCount) {
+                    smsHeader.concatRef = concatRef;
+                }
                 break;
             case ELT_ID_APPLICATION_PORT_ADDRESSING_8_BIT:
                 portAddrs = new PortAddrs();
diff --git a/telephony/java/com/android/internal/telephony/TelephonyEventLog.java b/telephony/java/com/android/internal/telephony/TelephonyEventLog.java
index 97f9d7d..cdce488 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyEventLog.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyEventLog.java
@@ -30,4 +30,6 @@
     public static final int EVENT_LOG_CGREG_FAIL = 50107;
     public static final int EVENT_LOG_DATA_STATE_RADIO_OFF = 50108;
     public static final int EVENT_LOG_PDP_NETWORK_DROP = 50109;
+    public static final int EVENT_LOG_CDMA_DATA_SETUP_FAILED = 50110;
+    public static final int EVENT_LOG_CDMA_DATA_DROP = 50111;
 }
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
index 2cbad78..a9c0f46 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnection.java
@@ -146,12 +146,16 @@
                 null, obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE));
     }
 
+    private void tearDownData(Message msg) {
+        if (phone.mCM.getRadioState().isOn()) {
+            phone.mCM.deactivateDataCall(cid, obtainMessage(EVENT_DEACTIVATE_DONE, msg));
+        }
+    }
+
     protected void disconnect(Message msg) {
         onDisconnect = msg;
         if (state == State.ACTIVE) {
-            if (phone.mCM.getRadioState().isOn()) {
-                phone.mCM.deactivateDataCall(cid, obtainMessage(EVENT_DEACTIVATE_DONE, msg));
-            }
+            tearDownData(msg);
         } else if (state == State.ACTIVATING) {
             receivedDisconnectReq = true;
         } else {
@@ -280,7 +284,7 @@
                 // Don't bother reporting success if there's already a
                 // pending disconnect request, since DataConnectionTracker
                 // has already updated its state.
-                disconnect(onDisconnect);
+                tearDownData(onDisconnect);
             } else {
                 String[] response = ((String[]) ar.result);
                 cid = Integer.parseInt(response[0]);
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
index 64f9387..bf58ab7 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java
@@ -39,6 +39,7 @@
 import android.provider.Settings.SettingNotFoundException;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
+import android.telephony.cdma.CdmaCellLocation;
 import android.util.EventLog;
 import android.text.TextUtils;
 import android.util.Log;
@@ -55,10 +56,6 @@
 import java.util.ArrayList;
 
 /**
- * WINK:TODO: In GsmDataConnectionTracker there are
- *            EventLog's used quite a few places maybe
- *            more need to be added in this file?
- *
  * {@hide}
  */
 public final class CdmaDataConnectionTracker extends DataConnectionTracker {
@@ -312,13 +309,11 @@
         Log.d(LOG_TAG, "setDataEnabled("+enable+") isEnabled=" + isEnabled);
         if (!isEnabled && enable) {
             setEnabled(EXTERNAL_NETWORK_DEFAULT_ID, true);
-            return trySetupData(Phone.REASON_DATA_ENABLED);
+            sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
         } else if (!enable) {
             setEnabled(EXTERNAL_NETWORK_DEFAULT_ID, false);
             cleanUpConnection(true, Phone.REASON_DATA_DISABLED);
-            return true;
-        } else // isEnabled && enable
-
+        }
         return true;
     }
 
@@ -363,6 +358,7 @@
 
         int psState = mCdmaPhone.mSST.getCurrentCdmaDataConnectionState();
         boolean roaming = phone.getServiceState().getRoaming();
+        boolean desiredPowerState = mCdmaPhone.mSST.getDesiredPowerState();
 
         if ((state == State.IDLE || state == State.SCANNING)
                 && (psState == ServiceState.RADIO_TECHNOLOGY_1xRTT ||
@@ -372,7 +368,8 @@
                         mCdmaPhone.mRuimRecords.getRecordsLoaded())
                 && (mCdmaPhone.mSST.isConcurrentVoiceAndData() ||
                         phone.getState() == Phone.State.IDLE )
-                && isDataAllowed()) {
+                && isDataAllowed()
+                && desiredPowerState) {
 
             return setupData(reason);
 
@@ -387,7 +384,8 @@
                     " phoneState=" + phone.getState() +
                     " dataEnabled=" + getAnyDataEnabled() +
                     " roaming=" + roaming +
-                    " dataOnRoamingEnable=" + getDataOnRoamingEnabled());
+                    " dataOnRoamingEnable=" + getDataOnRoamingEnabled() +
+                    " desiredPowerState=" + desiredPowerState);
             }
             return false;
         }
@@ -578,7 +576,14 @@
                 }
 
                 if (sentSinceLastRecv >= NUMBER_SENT_PACKETS_OF_HANG) {
-                    // we already have NUMBER_SENT_PACKETS sent without ack
+                    // Packets sent without ack exceeded threshold.
+
+                    if (mNoRecvPollCount == 0) {
+                        EventLog.writeEvent(
+                                TelephonyEventLog.EVENT_LOG_RADIO_RESET_COUNTDOWN_TRIGGERED,
+                                sentSinceLastRecv);
+                    }
+
                     if (mNoRecvPollCount < NO_RECV_POLL_LIMIT) {
                         mNoRecvPollCount++;
                         // Slow down the poll interval to let things happen
@@ -590,6 +595,8 @@
                         netStatPollEnabled = false;
                         stopNetStatPoll();
                         restartRadio();
+                        EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_RADIO_RESET,
+                                NO_RECV_POLL_LIMIT);
                     }
                 } else {
                     mNoRecvPollCount = 0;
@@ -845,6 +852,13 @@
             if (state == State.FAILED) {
                 cleanUpConnection(false, Phone.REASON_CDMA_DATA_DETACHED);
                 nextReconnectDelay = RECONNECT_DELAY_INITIAL_MILLIS;
+
+                CdmaCellLocation loc = (CdmaCellLocation)(phone.getCellLocation());
+                int bsid = (loc != null) ? loc.getBaseStationId() : -1;
+
+                EventLog.List val = new EventLog.List(bsid,
+                        TelephonyManager.getDefault().getNetworkType());
+                EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_CDMA_DATA_SETUP_FAILED, val);
             }
             trySetupData(Phone.REASON_CDMA_DATA_DETACHED);
         }
@@ -870,10 +884,11 @@
             }
         } else {
 
-            int cid = -1;
-            EventLog.List val = new EventLog.List(cid,
+            CdmaCellLocation loc = (CdmaCellLocation)(phone.getCellLocation());
+            int bsid = (loc != null) ? loc.getBaseStationId() : -1;
+            EventLog.List val = new EventLog.List(bsid,
                     TelephonyManager.getDefault().getNetworkType());
-            EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_PDP_NETWORK_DROP, val);
+            EventLog.writeEvent(TelephonyEventLog.EVENT_LOG_CDMA_DATA_DROP, val);
 
             cleanUpConnection(true, null);
         }
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
index 1d7aaf1..49e2daf 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java
@@ -478,7 +478,8 @@
             setEnabled(Phone.APN_TYPE_DEFAULT, true);
             // trySetupData() will be a no-op if we are currently
             // connected to the MMS APN
-            return trySetupData(Phone.REASON_DATA_ENABLED);
+            sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
+            return true;
         } else if (!enable) {
             setEnabled(Phone.APN_TYPE_DEFAULT, false);
             // Don't tear down if there is an active APN and it handles MMS or SUPL.
@@ -579,6 +580,7 @@
 
         int gprsState = ((GSMPhone) phone).mSST.getCurrentGprsState();
         boolean roaming = phone.getServiceState().getRoaming();
+        boolean desiredPowerState = ((GSMPhone) phone).mSST.getDesiredPowerState();
 
         if ((state == State.IDLE || state == State.SCANNING)
                 && (gprsState == ServiceState.STATE_IN_SERVICE || noAutoAttach)
@@ -586,7 +588,8 @@
                 && ( ((GSMPhone) phone).mSST.isConcurrentVoiceAndData() ||
                      phone.getState() == Phone.State.IDLE )
                 && isDataAllowed()
-                && !mIsPsRestricted ) {
+                && !mIsPsRestricted
+                && desiredPowerState ) {
 
             if (state == State.IDLE) {
                 waitingApns = buildWaitingApns();
@@ -614,7 +617,8 @@
                     " dataEnabled=" + getAnyDataEnabled() +
                     " roaming=" + roaming +
                     " dataOnRoamingEnable=" + getDataOnRoamingEnabled() +
-                    " ps restricted=" + mIsPsRestricted);
+                    " ps restricted=" + mIsPsRestricted +
+                    " desiredPowerState=" + desiredPowerState);
             return false;
         }
     }
diff --git a/telephony/java/com/android/internal/telephony/gsm/MccTable.java b/telephony/java/com/android/internal/telephony/gsm/MccTable.java
index e18da56..22b1f4f 100644
--- a/telephony/java/com/android/internal/telephony/gsm/MccTable.java
+++ b/telephony/java/com/android/internal/telephony/gsm/MccTable.java
@@ -35,6 +35,7 @@
         int smallestDigitsMnc;
         String timezone;
         String language;
+        int wifiChannelsAllowed;
 
         MccEntry(int mnc, String iso, int smallestDigitsMCC) {
             this(mnc, iso, smallestDigitsMCC, null);
@@ -45,11 +46,16 @@
         }
 
         MccEntry(int mnc, String iso, int smallestDigitsMCC, String timezone, String language) {
+            this(mnc, iso, smallestDigitsMCC, timezone, language, 0);
+        }
+
+        MccEntry(int mnc, String iso, int smallestDigitsMCC, String timezone, String language, int wifiChannels) {
             this.mcc = mnc;
             this.iso = iso;
             this.smallestDigitsMnc = smallestDigitsMCC;
             this.timezone = timezone;
             this.language = language;
+            this.wifiChannelsAllowed = wifiChannels;
         }
 
         public int compareTo(MccEntry o)
@@ -148,6 +154,23 @@
         }
     }
 
+    /**
+     * Given a GSM Mobile Country Code, returns
+     * the number of wifi channels allowed in that country.
+     * Returns 0 if unavailable
+     */
+    public static int wifiChannelsForMcc(int mcc) {
+        MccEntry entry;
+
+        entry = entryForMcc(mcc);
+
+        if (entry == null) {
+            return 0;
+        } else {
+            return entry.wifiChannelsAllowed;
+        }
+    }
+
     static {
         table = new ArrayList<MccEntry>(240);
 
@@ -169,7 +192,7 @@
          */
 
 		table.add(new MccEntry(202,"gr",2));	//Greece
-		table.add(new MccEntry(204,"nl",2,"Europe/Amsterdam","nl"));	//Netherlands (Kingdom of the)
+		table.add(new MccEntry(204,"nl",2,"Europe/Amsterdam","nl",13)); //Netherlands (Kingdom of the)
 		table.add(new MccEntry(206,"be",2));	//Belgium
 		table.add(new MccEntry(208,"fr",2,"Europe/Paris","fr"));	//France
 		table.add(new MccEntry(212,"mc",2));	//Monaco (Principality of)
@@ -183,11 +206,11 @@
 		table.add(new MccEntry(225,"va",2,"Europe/Rome","it"));	//Vatican City State
 		table.add(new MccEntry(226,"ro",2));	//Romania
 		table.add(new MccEntry(228,"ch",2,"Europe/Zurich","de"));	//Switzerland (Confederation of)
-		table.add(new MccEntry(230,"cz",2,"Europe/Prague","cs"));	//Czech Republic
+		table.add(new MccEntry(230,"cz",2,"Europe/Prague","cs", 13));	//Czech Republic
 		table.add(new MccEntry(231,"sk",2));	//Slovak Republic
-		table.add(new MccEntry(232,"at",2,"Europe/Vienna","de"));	//Austria
-		table.add(new MccEntry(234,"gb",2,"Europe/London","en"));	//United Kingdom of Great Britain and Northern Ireland
-		table.add(new MccEntry(235,"gb",2,"Europe/London","en"));	//United Kingdom of Great Britain and Northern Ireland
+		table.add(new MccEntry(232,"at",2,"Europe/Vienna","de", 13));   //Austria
+		table.add(new MccEntry(234,"gb",2,"Europe/London","en", 13));   //United Kingdom of Great Britain and Northern Ireland
+		table.add(new MccEntry(235,"gb",2,"Europe/London","en", 13));   //United Kingdom of Great Britain and Northern Ireland
 		table.add(new MccEntry(238,"dk",2));	//Denmark
 		table.add(new MccEntry(240,"se",2));	//Sweden
 		table.add(new MccEntry(242,"no",2));	//Norway
@@ -200,7 +223,7 @@
 		table.add(new MccEntry(257,"by",2));	//Belarus (Republic of)
 		table.add(new MccEntry(259,"md",2));	//Moldova (Republic of)
 		table.add(new MccEntry(260,"pl",2,"Europe/Warsaw"));	//Poland (Republic of)
-		table.add(new MccEntry(262,"de",2,"Europe/Berlin","de"));	//Germany (Federal Republic of)
+		table.add(new MccEntry(262,"de",2,"Europe/Berlin","de", 13));   //Germany (Federal Republic of)
 		table.add(new MccEntry(266,"gi",2));	//Gibraltar
 		table.add(new MccEntry(268,"pt",2));	//Portugal
 		table.add(new MccEntry(270,"lu",2));	//Luxembourg
@@ -219,15 +242,15 @@
 		table.add(new MccEntry(293,"sl",2));	//Slovenia (Republic of)
                 table.add(new MccEntry(294,"mk",2));   //The Former Yugoslav Republic of Macedonia
 		table.add(new MccEntry(295,"li",2));	//Liechtenstein (Principality of)
-		table.add(new MccEntry(302,"ca",2));	//Canada
+		table.add(new MccEntry(302,"ca",2, "", "", 11));        //Canada
 		table.add(new MccEntry(308,"pm",2));	//Saint Pierre and Miquelon (Collectivit territoriale de la Rpublique franaise)
-		table.add(new MccEntry(310,"us",3,"","en"));	//United States of America
-		table.add(new MccEntry(311,"us",3,"","en"));	//United States of America
-		table.add(new MccEntry(312,"us",3,"","en"));	//United States of America
-		table.add(new MccEntry(313,"us",3,"","en"));	//United States of America
-		table.add(new MccEntry(314,"us",3,"","en"));	//United States of America
-		table.add(new MccEntry(315,"us",3,"","en"));	//United States of America
-		table.add(new MccEntry(316,"us",3,"","en"));	//United States of America
+		table.add(new MccEntry(310,"us",3,"","en", 11));        //United States of America
+		table.add(new MccEntry(311,"us",3,"","en", 11));        //United States of America
+		table.add(new MccEntry(312,"us",3,"","en", 11));        //United States of America
+		table.add(new MccEntry(313,"us",3,"","en", 11));        //United States of America
+		table.add(new MccEntry(314,"us",3,"","en", 11));        //United States of America
+		table.add(new MccEntry(315,"us",3,"","en", 11));        //United States of America
+		table.add(new MccEntry(316,"us",3,"","en", 11));        //United States of America
 		table.add(new MccEntry(330,"pr",2));	//Puerto Rico
 		table.add(new MccEntry(332,"vi",2));	//United States Virgin Islands
 		table.add(new MccEntry(334,"mx",3));	//Mexico
@@ -283,8 +306,8 @@
 		table.add(new MccEntry(436,"tj",2));	//Tajikistan (Republic of)
 		table.add(new MccEntry(437,"kg",2));	//Kyrgyz Republic
 		table.add(new MccEntry(438,"tm",2));	//Turkmenistan
-		table.add(new MccEntry(440,"jp",2,"Asia/Tokyo","ja"));	//Japan
-		table.add(new MccEntry(441,"jp",2,"Asia/Tokyo","ja"));	//Japan
+		table.add(new MccEntry(440,"jp",2,"Asia/Tokyo","ja", 14));              //Japan
+		table.add(new MccEntry(441,"jp",2,"Asia/Tokyo","ja", 14));              //Japan
 		table.add(new MccEntry(450,"kr",2));	//Korea (Republic of)
 		table.add(new MccEntry(452,"vn",2));	//Viet Nam (Socialist Republic of)
 		table.add(new MccEntry(454,"hk",2));	//"Hong Kong, China"
@@ -298,12 +321,12 @@
 		table.add(new MccEntry(470,"bd",2));	//Bangladesh (People's Republic of)
 		table.add(new MccEntry(472,"mv",2));	//Maldives (Republic of)
 		table.add(new MccEntry(502,"my",2));	//Malaysia
-		table.add(new MccEntry(505,"au",2,"Australia/Sydney","en"));	//Australia
+		table.add(new MccEntry(505,"au",2,"Australia/Sydney","en", 11));        //Australia
 		table.add(new MccEntry(510,"id",2));	//Indonesia (Republic of)
 		table.add(new MccEntry(514,"tl",2));	//Democratic Republic of Timor-Leste
 		table.add(new MccEntry(515,"ph",2));	//Philippines (Republic of the)
 		table.add(new MccEntry(520,"th",2));	//Thailand
-		table.add(new MccEntry(525,"sg",2,"Singapore","en"));	//Singapore (Republic of)
+		table.add(new MccEntry(525,"sg",2,"Singapore","en", 11));               //Singapore (Republic of)
 		table.add(new MccEntry(528,"bn",2));	//Brunei Darussalam
 		table.add(new MccEntry(530,"nz",2,"Pacific/Auckland", "en"));	//New Zealand
 		table.add(new MccEntry(534,"mp",2));	//Northern Mariana Islands (Commonwealth of the)
diff --git a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
index f9015d9..fb45c7c 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SIMRecords.java
@@ -21,11 +21,13 @@
 import android.app.IActivityManager;
 import android.content.Context;
 import android.content.res.Configuration;
+import android.net.wifi.WifiManager;
 import android.os.AsyncResult;
 import android.os.Handler;
 import android.os.Message;
 import android.os.SystemProperties;
 import android.os.Registrant;
+import android.provider.Settings;
 import android.util.Log;
 import java.util.ArrayList;
 
@@ -513,6 +515,29 @@
         phone.setSystemLocale(language, country);
     }
 
+    /**
+     * If the number of allowed wifi channels has not been set, set it based on
+     * the MCC of the SIM.
+     * @param mcc Mobile Country Code of the SIM
+     */
+    private void setWifiChannelsFromMccIfNeeded(int mcc) {
+        int wifiChannels = MccTable.wifiChannelsForMcc(mcc);
+
+        if (wifiChannels != 0) {
+            Context context = phone.getContext();
+            // only set to this default if the user hasn't manually set it
+            try {
+                Settings.Secure.getInt(context.getContentResolver(),
+                        Settings.Secure.WIFI_NUM_ALLOWED_CHANNELS);
+            } catch (Settings.SettingNotFoundException e) {
+                WifiManager wM = (WifiManager)
+                        context.getSystemService(Context.WIFI_SERVICE);
+                // don't persist
+                wM.setNumAllowedChannels(wifiChannels, false);
+            }
+        }
+    }
+
     //***** Overridden from Handler
     public void handleMessage(Message msg) {
         AsyncResult ar;
@@ -559,6 +584,7 @@
                 int mcc = Integer.parseInt(imsi.substring(0, 3));
                 setTimezoneFromMccIfNeeded(mcc);
                 setLocaleFromMccIfNeeded(mcc);
+                setWifiChannelsFromMccIfNeeded(mcc);
             break;
 
             case EVENT_GET_MBI_DONE:
diff --git a/test-runner/android/test/mock/MockContentProvider.java b/test-runner/android/test/mock/MockContentProvider.java
index fdba2e2..757c72d 100644
--- a/test-runner/android/test/mock/MockContentProvider.java
+++ b/test-runner/android/test/mock/MockContentProvider.java
@@ -20,6 +20,9 @@
 import android.content.IContentProvider;
 import android.content.Entity;
 import android.content.EntityIterator;
+import android.content.ContentProviderResult;
+import android.content.ContentProviderOperation;
+import android.content.OperationApplicationException;
 import android.content.res.AssetFileDescriptor;
 import android.database.Cursor;
 import android.database.CursorWindow;
@@ -49,7 +52,7 @@
         return 0;
     }
 
-    public Uri[] bulkInsertEntities(Uri uri, Entity[] entities) throws RemoteException {
+    public Uri insertEntity(Uri uri, Entity entities) throws RemoteException {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
 
@@ -87,7 +90,11 @@
             throws FileNotFoundException {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
-    
+
+    public ContentProviderResult[] applyBatch(ContentProviderOperation[] operations) throws RemoteException, OperationApplicationException {
+        throw new UnsupportedOperationException("unimplemented mock method");
+    }
+
     @SuppressWarnings("unused")
     public Cursor query(Uri url, String[] projection, String selection, String[] selectionArgs,
             String sortOrder) throws RemoteException {
@@ -105,7 +112,7 @@
         throw new UnsupportedOperationException("unimplemented mock method");
     }
 
-    public int[] bulkUpdateEntities(Uri uri, Entity[] entities) throws RemoteException {
+    public int updateEntity(Uri uri, Entity entity) throws RemoteException {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
 
diff --git a/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java b/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java
index f8d5d4d..75fd157 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/CdmaSmsTest.java
@@ -169,6 +169,43 @@
     }
 
     @SmallTest
+    public void testUserDataHeaderIllegalConcatRef() throws Exception {
+        BearerData bearerData = new BearerData();
+        bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
+        bearerData.messageId = 55;
+        SmsHeader.ConcatRef concatRef = new SmsHeader.ConcatRef();
+        concatRef.refNumber = 0x10;
+        concatRef.msgCount = 0;
+        concatRef.seqNumber = 2;
+        concatRef.isEightBits = true;
+        SmsHeader smsHeader = new SmsHeader();
+        smsHeader.concatRef = concatRef;
+        byte[] encodedHeader = SmsHeader.toByteArray(smsHeader);
+        SmsHeader decodedHeader = SmsHeader.fromByteArray(encodedHeader);
+        assertEquals(decodedHeader.concatRef, null);
+        concatRef.isEightBits = false;
+        encodedHeader = SmsHeader.toByteArray(smsHeader);
+        decodedHeader = SmsHeader.fromByteArray(encodedHeader);
+        assertEquals(decodedHeader.concatRef, null);
+        concatRef.msgCount = 1;
+        concatRef.seqNumber = 2;
+        encodedHeader = SmsHeader.toByteArray(smsHeader);
+        decodedHeader = SmsHeader.fromByteArray(encodedHeader);
+        assertEquals(decodedHeader.concatRef, null);
+        concatRef.msgCount = 1;
+        concatRef.seqNumber = 0;
+        encodedHeader = SmsHeader.toByteArray(smsHeader);
+        decodedHeader = SmsHeader.fromByteArray(encodedHeader);
+        assertEquals(decodedHeader.concatRef, null);
+        concatRef.msgCount = 2;
+        concatRef.seqNumber = 1;
+        encodedHeader = SmsHeader.toByteArray(smsHeader);
+        decodedHeader = SmsHeader.fromByteArray(encodedHeader);
+        assertEquals(decodedHeader.concatRef.msgCount, 2);
+        assertEquals(decodedHeader.concatRef.seqNumber, 1);
+    }
+
+    @SmallTest
     public void testUserDataHeaderMixedFeedback() throws Exception {
         BearerData bearerData = new BearerData();
         bearerData.messageType = BearerData.MESSAGE_TYPE_DELIVER;
diff --git a/tests/AndroidTests/src/com/android/unit_tests/content/ContentProviderOperationTest.java b/tests/AndroidTests/src/com/android/unit_tests/content/ContentProviderOperationTest.java
deleted file mode 100644
index 46a12fd..0000000
--- a/tests/AndroidTests/src/com/android/unit_tests/content/ContentProviderOperationTest.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.unit_tests.content;
-
-import android.test.suitebuilder.annotation.SmallTest;
-import android.net.Uri;
-import android.content.ContentValues;
-import android.content.ContentProviderOperation;
-import android.content.OperationApplicationException;
-import android.content.ContentProviderResult;
-import android.content.ContentProvider;
-import android.text.TextUtils;
-import android.database.Cursor;
-import junit.framework.TestCase;
-
-import java.util.Map;
-import java.util.Hashtable;
-
-@SmallTest
-public class ContentProviderOperationTest extends TestCase {
-    private final static Uri sTestUri1 = Uri.parse("content://authority/blah");
-    private final static ContentValues sTestValues1;
-
-    static {
-        sTestValues1 = new ContentValues();
-        sTestValues1.put("a", 1);
-        sTestValues1.put("b", "two");
-    }
-
-    public void testInsert() throws OperationApplicationException {
-        ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1)
-                .withValues(sTestValues1)
-                .build();
-        ContentProviderResult result = op1.apply(new TestContentProvider() {
-            public Uri insert(Uri uri, ContentValues values) {
-                assertEquals(sTestUri1.toString(), uri.toString());
-                assertEquals(sTestValues1.toString(), values.toString());
-                return uri.buildUpon().appendPath("19").build();
-            }
-        }, null, 0);
-        assertEquals(sTestUri1.buildUpon().appendPath("19").toString(), result.uri.toString());
-    }
-
-    public void testInsertNoValues() throws OperationApplicationException {
-        ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1)
-                .build();
-        ContentProviderResult result = op1.apply(new TestContentProvider() {
-            public Uri insert(Uri uri, ContentValues values) {
-                assertEquals(sTestUri1.toString(), uri.toString());
-                assertNull(values);
-                return uri.buildUpon().appendPath("19").build();
-            }
-        }, null, 0);
-        assertEquals(sTestUri1.buildUpon().appendPath("19").toString(), result.uri.toString());
-    }
-
-    public void testInsertFailed() {
-        ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1)
-                .withValues(sTestValues1)
-                .build();
-        try {
-            op1.apply(new TestContentProvider() {
-                public Uri insert(Uri uri, ContentValues values) {
-                    assertEquals(sTestUri1.toString(), uri.toString());
-                    assertEquals(sTestValues1.toString(), values.toString());
-                    return null;
-                }
-            }, null, 0);
-            fail("the apply should have thrown an OperationApplicationException");
-        } catch (OperationApplicationException e) {
-            // this is the expected case
-        }
-    }
-
-    public void testInsertWithBackRefs() throws OperationApplicationException {
-        ContentValues valuesBackRefs = new ContentValues();
-        valuesBackRefs.put("a1", 3);
-        valuesBackRefs.put("a2", 1);
-
-        ContentProviderResult[] previousResults = new ContentProviderResult[4];
-        previousResults[0] = new ContentProviderResult(100);
-        previousResults[1] = new ContentProviderResult(101);
-        previousResults[2] = new ContentProviderResult(102);
-        previousResults[3] = new ContentProviderResult(103);
-        ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1)
-                .withValues(sTestValues1)
-                .withValueBackReferences(valuesBackRefs)
-                .build();
-        ContentProviderResult result = op1.apply(new TestContentProvider() {
-            public Uri insert(Uri uri, ContentValues values) {
-                assertEquals(sTestUri1.toString(), uri.toString());
-                ContentValues expected = new ContentValues(sTestValues1);
-                expected.put("a1", 103);
-                expected.put("a2", 101);
-                assertEquals(expected.toString(), values.toString());
-                return uri.buildUpon().appendPath("19").build();
-            }
-        }, previousResults, previousResults.length);
-        assertEquals(sTestUri1.buildUpon().appendPath("19").toString(), result.uri.toString());
-    }
-
-    public void testUpdate() throws OperationApplicationException {
-        ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1)
-                .withValues(sTestValues1)
-                .build();
-        ContentProviderResult[] backRefs = new ContentProviderResult[2];
-        ContentProviderResult result = op1.apply(new TestContentProvider() {
-            public Uri insert(Uri uri, ContentValues values) {
-                assertEquals(sTestUri1.toString(), uri.toString());
-                assertEquals(sTestValues1.toString(), values.toString());
-                return uri.buildUpon().appendPath("19").build();
-            }
-        }, backRefs, 1);
-        assertEquals(sTestUri1.buildUpon().appendPath("19").toString(), result.uri.toString());
-    }
-
-    public void testValueBackRefs() {
-        ContentValues values = new ContentValues();
-        values.put("a", "in1");
-        values.put("a2", "in2");
-        values.put("b", "in3");
-        values.put("c", "in4");
-
-        ContentProviderResult[] previousResults = new ContentProviderResult[4];
-        previousResults[0] = new ContentProviderResult(100);
-        previousResults[1] = new ContentProviderResult(101);
-        previousResults[2] = new ContentProviderResult(102);
-        previousResults[3] = new ContentProviderResult(103);
-
-        ContentValues valuesBackRefs = new ContentValues();
-        valuesBackRefs.put("a1", 3); // a1 -> 103
-        valuesBackRefs.put("a2", 1); // a2 -> 101
-        valuesBackRefs.put("a3", 2); // a3 -> 102
-
-        ContentValues expectedValues = new ContentValues(values);
-        expectedValues.put("a1", "103");
-        expectedValues.put("a2", "101");
-        expectedValues.put("a3", "102");
-
-        ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1)
-                .withValues(values)
-                .withValueBackReferences(valuesBackRefs)
-                .build();
-        ContentValues v2 = op1.resolveValueBackReferences(previousResults, previousResults.length);
-        assertEquals(expectedValues, v2);
-    }
-
-    public void testSelectionBackRefs() {
-        Map<Integer, Integer> selectionBackRefs = new Hashtable<Integer, Integer>();
-        selectionBackRefs.put(1, 3);
-        selectionBackRefs.put(2, 1);
-        selectionBackRefs.put(4, 2);
-
-        ContentProviderResult[] previousResults = new ContentProviderResult[4];
-        previousResults[0] = new ContentProviderResult(100);
-        previousResults[1] = new ContentProviderResult(101);
-        previousResults[2] = new ContentProviderResult(102);
-        previousResults[3] = new ContentProviderResult(103);
-
-        String[] selectionArgs = new String[]{"a", null, null, "b", null};
-
-        ContentProviderOperation op1 = ContentProviderOperation.newUpdate(sTestUri1)
-                .withSelectionBackReferences(selectionBackRefs)
-                .withSelection("unused", selectionArgs)
-                .build();
-        String[] s2 = op1.resolveSelectionArgsBackReferences(
-                previousResults, previousResults.length);
-        assertEquals("a,103,101,b,102", TextUtils.join(",", s2));
-    }
-
-    static class TestContentProvider extends ContentProvider {
-        public boolean onCreate() {
-            throw new UnsupportedOperationException();
-        }
-
-        public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
-                String sortOrder) {
-            throw new UnsupportedOperationException();
-        }
-
-        public String getType(Uri uri) {
-            throw new UnsupportedOperationException();
-        }
-
-        public Uri insert(Uri uri, ContentValues values) {
-            throw new UnsupportedOperationException();
-        }
-
-        public int delete(Uri uri, String selection, String[] selectionArgs) {
-            throw new UnsupportedOperationException();
-        }
-
-        public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
-            throw new UnsupportedOperationException();
-        }
-    }
-}
\ No newline at end of file
diff --git a/tests/DumpRenderTree/AndroidManifest.xml b/tests/DumpRenderTree/AndroidManifest.xml
index 0e33d62..5442ec9 100644
--- a/tests/DumpRenderTree/AndroidManifest.xml
+++ b/tests/DumpRenderTree/AndroidManifest.xml
@@ -31,5 +31,6 @@
         android:targetPackage="com.android.dumprendertree"
         android:label="Layout test automation runner"
     />
-    <uses-permission android:name="android.permission.INTERNET"></uses-permission>
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.WRITE_SDCARD" />
 </manifest>
diff --git a/tests/FrameworkTest/tests/src/android/content/ContentProviderOperationTest.java b/tests/FrameworkTest/tests/src/android/content/ContentProviderOperationTest.java
new file mode 100644
index 0000000..27241b8
--- /dev/null
+++ b/tests/FrameworkTest/tests/src/android/content/ContentProviderOperationTest.java
@@ -0,0 +1,508 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content;
+
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Parcel;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.text.TextUtils;
+import junit.framework.TestCase;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+@SmallTest
+public class ContentProviderOperationTest extends TestCase {
+    private final static Uri sTestUri1 = Uri.parse("content://authority/blah");
+    private final static ContentValues sTestValues1;
+
+    private final static Class<ContentProviderOperation.Builder> CLASS_BUILDER =
+            ContentProviderOperation.Builder.class;
+    private final static Class<ContentProviderOperation> CLASS_OPERATION =
+            ContentProviderOperation.class;
+
+    static {
+        sTestValues1 = new ContentValues();
+        sTestValues1.put("a", 1);
+        sTestValues1.put("b", "two");
+    }
+
+    public void testInsert() throws OperationApplicationException {
+        ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1)
+                .withValues(sTestValues1)
+                .build();
+        ContentProviderResult result = op1.apply(new TestContentProvider() {
+            public Uri insert(Uri uri, ContentValues values) {
+                assertEquals(sTestUri1.toString(), uri.toString());
+                assertEquals(sTestValues1.toString(), values.toString());
+                return uri.buildUpon().appendPath("19").build();
+            }
+        }, null, 0);
+        assertEquals(sTestUri1.buildUpon().appendPath("19").toString(), result.uri.toString());
+    }
+
+    public void testInsertNoValues() throws OperationApplicationException {
+        ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1)
+                .build();
+        ContentProviderResult result = op1.apply(new TestContentProvider() {
+            public Uri insert(Uri uri, ContentValues values) {
+                assertEquals(sTestUri1.toString(), uri.toString());
+                assertNull(values);
+                return uri.buildUpon().appendPath("19").build();
+            }
+        }, null, 0);
+        assertEquals(sTestUri1.buildUpon().appendPath("19").toString(), result.uri.toString());
+    }
+
+    public void testInsertFailed() {
+        ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1)
+                .withValues(sTestValues1)
+                .build();
+        try {
+            op1.apply(new TestContentProvider() {
+                public Uri insert(Uri uri, ContentValues values) {
+                    assertEquals(sTestUri1.toString(), uri.toString());
+                    assertEquals(sTestValues1.toString(), values.toString());
+                    return null;
+                }
+            }, null, 0);
+            fail("the apply should have thrown an OperationApplicationException");
+        } catch (OperationApplicationException e) {
+            // this is the expected case
+        }
+    }
+
+    public void testInsertWithBackRefs() throws OperationApplicationException {
+        ContentValues valuesBackRefs = new ContentValues();
+        valuesBackRefs.put("a1", 3);
+        valuesBackRefs.put("a2", 1);
+
+        ContentProviderResult[] previousResults = new ContentProviderResult[4];
+        previousResults[0] = new ContentProviderResult(100);
+        previousResults[1] = new ContentProviderResult(101);
+        previousResults[2] = new ContentProviderResult(102);
+        previousResults[3] = new ContentProviderResult(103);
+        ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1)
+                .withValues(sTestValues1)
+                .withValueBackReferences(valuesBackRefs)
+                .build();
+        ContentProviderResult result = op1.apply(new TestContentProvider() {
+            public Uri insert(Uri uri, ContentValues values) {
+                assertEquals(sTestUri1.toString(), uri.toString());
+                ContentValues expected = new ContentValues(sTestValues1);
+                expected.put("a1", 103);
+                expected.put("a2", 101);
+                assertEquals(expected.toString(), values.toString());
+                return uri.buildUpon().appendPath("19").build();
+            }
+        }, previousResults, previousResults.length);
+        assertEquals(sTestUri1.buildUpon().appendPath("19").toString(), result.uri.toString());
+    }
+
+    public void testUpdate() throws OperationApplicationException {
+        ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1)
+                .withValues(sTestValues1)
+                .build();
+        ContentProviderResult[] backRefs = new ContentProviderResult[2];
+        ContentProviderResult result = op1.apply(new TestContentProvider() {
+            public Uri insert(Uri uri, ContentValues values) {
+                assertEquals(sTestUri1.toString(), uri.toString());
+                assertEquals(sTestValues1.toString(), values.toString());
+                return uri.buildUpon().appendPath("19").build();
+            }
+        }, backRefs, 1);
+        assertEquals(sTestUri1.buildUpon().appendPath("19").toString(), result.uri.toString());
+    }
+
+    public void testValueBackRefs() {
+        ContentValues values = new ContentValues();
+        values.put("a", "in1");
+        values.put("a2", "in2");
+        values.put("b", "in3");
+        values.put("c", "in4");
+
+        ContentProviderResult[] previousResults = new ContentProviderResult[4];
+        previousResults[0] = new ContentProviderResult(100);
+        previousResults[1] = new ContentProviderResult(101);
+        previousResults[2] = new ContentProviderResult(102);
+        previousResults[3] = new ContentProviderResult(103);
+
+        ContentValues valuesBackRefs = new ContentValues();
+        valuesBackRefs.put("a1", 3); // a1 -> 103
+        valuesBackRefs.put("a2", 1); // a2 -> 101
+        valuesBackRefs.put("a3", 2); // a3 -> 102
+
+        ContentValues expectedValues = new ContentValues(values);
+        expectedValues.put("a1", "103");
+        expectedValues.put("a2", "101");
+        expectedValues.put("a3", "102");
+
+        ContentProviderOperation op1 = ContentProviderOperation.newInsert(sTestUri1)
+                .withValues(values)
+                .withValueBackReferences(valuesBackRefs)
+                .build();
+        ContentValues v2 = op1.resolveValueBackReferences(previousResults, previousResults.length);
+        assertEquals(expectedValues, v2);
+    }
+
+    public void testSelectionBackRefs() {
+        Map<Integer, Integer> selectionBackRefs = new Hashtable<Integer, Integer>();
+        selectionBackRefs.put(1, 3);
+        selectionBackRefs.put(2, 1);
+        selectionBackRefs.put(4, 2);
+
+        ContentProviderResult[] previousResults = new ContentProviderResult[4];
+        previousResults[0] = new ContentProviderResult(100);
+        previousResults[1] = new ContentProviderResult(101);
+        previousResults[2] = new ContentProviderResult(102);
+        previousResults[3] = new ContentProviderResult(103);
+
+        String[] selectionArgs = new String[]{"a", null, null, "b", null};
+
+        ContentProviderOperation op1 = ContentProviderOperation.newUpdate(sTestUri1)
+                .withSelectionBackReferences(selectionBackRefs)
+                .withSelection("unused", selectionArgs)
+                .build();
+        String[] s2 = op1.resolveSelectionArgsBackReferences(
+                previousResults, previousResults.length);
+        assertEquals("a,103,101,b,102", TextUtils.join(",", s2));
+    }
+
+    public void testParcelingOperation() throws NoSuchFieldException, IllegalAccessException,
+            NoSuchMethodException, InvocationTargetException, InstantiationException {
+        Parcel parcel = Parcel.obtain();
+        ContentProviderOperation op1;
+        ContentProviderOperation op2;
+
+        HashMap<Integer, Integer> selArgsBackRef = new HashMap<Integer, Integer>();
+        selArgsBackRef.put(1, 2);
+        selArgsBackRef.put(3, 4);
+
+        ContentValues values = new ContentValues();
+        values.put("v1", "val1");
+        values.put("v2", "43");
+
+        ContentValues valuesBackRef = new ContentValues();
+        values.put("v3", "val3");
+        values.put("v4", "44");
+
+        try {
+            ContentProviderOperation.Builder builder = ContentProviderOperation.newInsert(
+                    Uri.parse("content://goo/bar"));
+
+            builderSetEntity(builder, new TestEntity("blah"));
+            builderSetExpectedCount(builder, 42);
+            builderSetSelection(builder, "selection");
+            builderSetSelectionArgs(builder, new String[]{"a", "b"});
+            builderSetSelectionArgsBackReferences(builder, selArgsBackRef);
+            builderSetValues(builder, values);
+            builderSetValuesBackReferences(builder, valuesBackRef);
+
+            op1 = newOperationFromBuilder(builder);
+            op1.writeToParcel(parcel, 0);
+            parcel.setDataPosition(0);
+            op2 = ContentProviderOperation.CREATOR.createFromParcel(parcel);
+
+            assertEquals(1 /* ContentProviderOperation.TYPE_INSERT */, operationGetType(op2));
+            assertEquals("content://goo/bar", operationGetUri(op2).toString());
+            assertEquals("blah", ((TestEntity) operationGetEntity(op2)).mValue);
+            assertEquals(Integer.valueOf(42), operationGetExpectedCount(op2));
+            assertEquals("selection", operationGetSelection(op2));
+            assertEquals(2, operationGetSelectionArgs(op2).length);
+            assertEquals("a", operationGetSelectionArgs(op2)[0]);
+            assertEquals("b", operationGetSelectionArgs(op2)[1]);
+            assertEquals(values, operationGetValues(op2));
+            assertEquals(valuesBackRef, operationGetValuesBackReferences(op2));
+            assertEquals(2, operationGetSelectionArgsBackReferences(op2).size());
+            assertEquals(Integer.valueOf(2), operationGetSelectionArgsBackReferences(op2).get(1));
+            assertEquals(Integer.valueOf(4), operationGetSelectionArgsBackReferences(op2).get(3));
+        } finally {
+            parcel.recycle();
+        }
+
+        try {
+            ContentProviderOperation.Builder builder = ContentProviderOperation.newUpdate(
+                    Uri.parse("content://goo/bar"));
+
+            builderSetSelectionArgsBackReferences(builder, selArgsBackRef);
+
+            op1 = newOperationFromBuilder(builder);
+            op1.writeToParcel(parcel, 0);
+            parcel.setDataPosition(0);
+            op2 = ContentProviderOperation.CREATOR.createFromParcel(parcel);
+            assertEquals(2 /* ContentProviderOperation.TYPE_UPDATE */, operationGetType(op2));
+            assertEquals("content://goo/bar", operationGetUri(op2).toString());
+            assertNull(operationGetEntity(op2));
+            assertNull(operationGetExpectedCount(op2));
+            assertNull(operationGetSelection(op2));
+            assertNull(operationGetSelectionArgs(op2));
+            assertNull(operationGetValues(op2));
+            assertNull(operationGetValuesBackReferences(op2));
+            assertEquals(2, operationGetSelectionArgsBackReferences(op2).size());
+            assertEquals(Integer.valueOf(2), operationGetSelectionArgsBackReferences(op2).get(1));
+            assertEquals(Integer.valueOf(4), operationGetSelectionArgsBackReferences(op2).get(3));
+        } finally {
+            parcel.recycle();
+        }
+
+        try {
+            ContentProviderOperation.Builder builder = ContentProviderOperation.newDelete(
+                    Uri.parse("content://goo/bar"));
+
+            op1 = newOperationFromBuilder(builder);
+            op1.writeToParcel(parcel, 0);
+            parcel.setDataPosition(0);
+            op2 = ContentProviderOperation.CREATOR.createFromParcel(parcel);
+            assertEquals(3 /* ContentProviderOperation.TYPE_DELETE */, operationGetType(op2));
+            assertEquals("content://goo/bar", operationGetUri(op2).toString());
+            assertNull(operationGetEntity(op2));
+            assertNull(operationGetExpectedCount(op2));
+            assertNull(operationGetSelection(op2));
+            assertNull(operationGetSelectionArgs(op2));
+            assertNull(operationGetValues(op2));
+            assertNull(operationGetValuesBackReferences(op2));
+            assertNull(operationGetSelectionArgsBackReferences(op2));
+        } finally {
+            parcel.recycle();
+        }
+    }
+
+    private static ContentProviderOperation newOperationFromBuilder(
+            ContentProviderOperation.Builder builder)
+            throws NoSuchMethodException, InstantiationException, IllegalAccessException,
+            InvocationTargetException {
+        final Constructor constructor = CLASS_OPERATION.getDeclaredConstructor(CLASS_BUILDER);
+        constructor.setAccessible(true);
+        return (ContentProviderOperation) constructor.newInstance(builder);
+    }
+
+    private void builderSetSelectionArgsBackReferences(
+            ContentProviderOperation.Builder builder, HashMap<Integer, Integer> selArgsBackRef)
+            throws NoSuchFieldException, IllegalAccessException {
+        Field field;
+        field = CLASS_BUILDER.getDeclaredField("mSelectionArgsBackReferences");
+        field.setAccessible(true);
+        field.set(builder, selArgsBackRef);
+    }
+
+    private void builderSetValuesBackReferences(
+            ContentProviderOperation.Builder builder, ContentValues valuesBackReferences)
+            throws NoSuchFieldException, IllegalAccessException {
+        Field field;
+        field = CLASS_BUILDER.getDeclaredField("mValuesBackReferences");
+        field.setAccessible(true);
+        field.set(builder, valuesBackReferences);
+    }
+
+    private void builderSetSelection(
+            ContentProviderOperation.Builder builder, String selection)
+            throws NoSuchFieldException, IllegalAccessException {
+        Field field;
+        field = CLASS_BUILDER.getDeclaredField("mSelection");
+        field.setAccessible(true);
+        field.set(builder, selection);
+    }
+
+    private void builderSetSelectionArgs(
+            ContentProviderOperation.Builder builder, String[] selArgs)
+            throws NoSuchFieldException, IllegalAccessException {
+        Field field;
+        field = CLASS_BUILDER.getDeclaredField("mSelectionArgs");
+        field.setAccessible(true);
+        field.set(builder, selArgs);
+    }
+
+    private void builderSetValues(
+            ContentProviderOperation.Builder builder, ContentValues values)
+            throws NoSuchFieldException, IllegalAccessException {
+        Field field;
+        field = CLASS_BUILDER.getDeclaredField("mValues");
+        field.setAccessible(true);
+        field.set(builder, values);
+    }
+
+    private void builderSetEntity(
+            ContentProviderOperation.Builder builder, Entity entity)
+            throws NoSuchFieldException, IllegalAccessException {
+        Field field;
+        field = CLASS_BUILDER.getDeclaredField("mEntity");
+        field.setAccessible(true);
+        field.set(builder, entity);
+    }
+
+    private void builderSetExpectedCount(
+            ContentProviderOperation.Builder builder, Integer expectedCount)
+            throws NoSuchFieldException, IllegalAccessException {
+        Field field;
+        field = CLASS_BUILDER.getDeclaredField("mExpectedCount");
+        field.setAccessible(true);
+        field.set(builder, expectedCount);
+    }
+
+    private int operationGetType(ContentProviderOperation operation)
+            throws NoSuchFieldException, IllegalAccessException {
+        final Field field = CLASS_OPERATION.getDeclaredField("mType");
+        field.setAccessible(true);
+        return field.getInt(operation);
+    }
+
+    private Uri operationGetUri(ContentProviderOperation operation)
+            throws NoSuchFieldException, IllegalAccessException {
+        final Field field = CLASS_OPERATION.getDeclaredField("mUri");
+        field.setAccessible(true);
+        return (Uri) field.get(operation);
+    }
+
+    private String operationGetSelection(ContentProviderOperation operation)
+            throws NoSuchFieldException, IllegalAccessException {
+        final Field field = CLASS_OPERATION.getDeclaredField("mSelection");
+        field.setAccessible(true);
+        return (String) field.get(operation);
+    }
+
+    private String[] operationGetSelectionArgs(ContentProviderOperation operation)
+            throws NoSuchFieldException, IllegalAccessException {
+        final Field field = CLASS_OPERATION.getDeclaredField("mSelectionArgs");
+        field.setAccessible(true);
+        return (String[]) field.get(operation);
+    }
+
+    private ContentValues operationGetValues(ContentProviderOperation operation)
+            throws NoSuchFieldException, IllegalAccessException {
+        final Field field = CLASS_OPERATION.getDeclaredField("mValues");
+        field.setAccessible(true);
+        return (ContentValues) field.get(operation);
+    }
+
+    private Entity operationGetEntity(ContentProviderOperation operation)
+            throws NoSuchFieldException, IllegalAccessException {
+        final Field field = CLASS_OPERATION.getDeclaredField("mEntity");
+        field.setAccessible(true);
+        return (Entity) field.get(operation);
+    }
+
+    private Integer operationGetExpectedCount(ContentProviderOperation operation)
+            throws NoSuchFieldException, IllegalAccessException {
+        final Field field = CLASS_OPERATION.getDeclaredField("mExpectedCount");
+        field.setAccessible(true);
+        return (Integer) field.get(operation);
+    }
+
+    private ContentValues operationGetValuesBackReferences(ContentProviderOperation operation)
+            throws NoSuchFieldException, IllegalAccessException {
+        final Field field = CLASS_OPERATION.getDeclaredField("mValuesBackReferences");
+        field.setAccessible(true);
+        return (ContentValues) field.get(operation);
+    }
+
+    private Map<Integer, Integer> operationGetSelectionArgsBackReferences(
+            ContentProviderOperation operation)
+            throws NoSuchFieldException, IllegalAccessException {
+        final Field field = CLASS_OPERATION.getDeclaredField("mSelectionArgsBackReferences");
+        field.setAccessible(true);
+        return (Map<Integer, Integer>) field.get(operation);
+    }
+
+    public static class TestEntity extends Entity {
+        public final String mValue;
+        public TestEntity(String value) {
+            mValue = value;
+        }
+
+        public TestEntity(Parcel source) {
+            mValue = source.readString();
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeString(mValue);
+        }
+
+        public static final Creator<TestEntity> CREATOR = new Creator<TestEntity>() {
+            public TestEntity createFromParcel(Parcel source) {
+                return new TestEntity(source);
+            }
+
+            public TestEntity[] newArray(int size) {
+                return new TestEntity[size];
+            }
+        };
+    }
+
+    public void testParcelingResult() {
+        Parcel parcel = Parcel.obtain();
+        ContentProviderResult result1;
+        ContentProviderResult result2;
+        try {
+            result1 = new ContentProviderResult(Uri.parse("content://goo/bar"));
+            result1.writeToParcel(parcel, 0);
+            parcel.setDataPosition(0);
+            result2 = ContentProviderResult.CREATOR.createFromParcel(parcel);
+            assertEquals("content://goo/bar", result2.uri.toString());
+            assertNull(result2.count);
+        } finally {
+            parcel.recycle();
+        }
+
+        parcel = Parcel.obtain();
+        try {
+            result1 = new ContentProviderResult(42);
+            result1.writeToParcel(parcel, 0);
+            parcel.setDataPosition(0);
+            result2 = ContentProviderResult.CREATOR.createFromParcel(parcel);
+            assertEquals(Integer.valueOf(42), result2.count);
+            assertNull(result2.uri);
+        } finally {
+            parcel.recycle();
+        }
+    }
+
+    static class TestContentProvider extends ContentProvider {
+        public boolean onCreate() {
+            throw new UnsupportedOperationException();
+        }
+
+        public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+                String sortOrder) {
+            throw new UnsupportedOperationException();
+        }
+
+        public String getType(Uri uri) {
+            throw new UnsupportedOperationException();
+        }
+
+        public Uri insert(Uri uri, ContentValues values) {
+            throw new UnsupportedOperationException();
+        }
+
+        public int delete(Uri uri, String selection, String[] selectionArgs) {
+            throw new UnsupportedOperationException();
+        }
+
+        public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+            throw new UnsupportedOperationException();
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/sketch/AndroidManifest.xml b/tests/sketch/AndroidManifest.xml
index 1f4333c..fbf3a09b 100755
--- a/tests/sketch/AndroidManifest.xml
+++ b/tests/sketch/AndroidManifest.xml
@@ -14,25 +14,32 @@
      limitations under the License.
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-      package="com.android.gesture.example"
-      android:versionCode="1"
-      android:versionName="1.0.0">
-      <uses-permission android:name="android.permission.READ_CONTACTS" />
-      <application android:icon="@drawable/icon" android:label="@string/app_name">
-        <activity android:name="com.android.gesture.example.GestureEntry"
-                  android:label="@string/app_name">
+    package="com.android.gesture.example">
+
+    <uses-permission android:name="android.permission.READ_CONTACTS" />
+    <uses-permission android:name="android.permission.WRITE_SDCARD" />
+
+    <application android:icon="@drawable/icon" android:label="@string/app_name">
+
+        <activity
+            android:name="com.android.gesture.example.GestureEntry"
+            android:label="@string/app_name">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
+
         <activity android:name="com.android.gesture.example.GestureLibViewer"/>
-        <activity android:name="com.android.gesture.example.ContactListGestureOverlay"
-                  android:label="@string/overlay_name">
+
+        <activity
+            android:name="com.android.gesture.example.ContactListGestureOverlay"
+            android:label="@string/overlay_name">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
+
     </application>
 </manifest> 
diff --git a/tests/sketch/res/layout/demo.xml b/tests/sketch/res/layout/demo.xml
index 8c9161a..c3a78cf 100755
--- a/tests/sketch/res/layout/demo.xml
+++ b/tests/sketch/res/layout/demo.xml
@@ -17,7 +17,8 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical"
     android:layout_width="fill_parent"
-    android:layout_height="wrap_content">
+    android:layout_height="fill_parent">
+
     <Spinner 
         android:id="@+id/spinner"
         android:layout_width="fill_parent"
@@ -25,10 +26,10 @@
         android:drawSelectorOnTop="true"
         android:prompt="@string/recognition_result"/>
     
-    <com.android.gesture.GestureOverlay 
+    <android.gesture.GestureOverlayView 
         android:id="@+id/drawingpad"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
-        android:layout_weight="1"/>
+        android:layout_weight="1" />
     
 </LinearLayout>
diff --git a/tests/sketch/res/layout/gestureviewer.xml b/tests/sketch/res/layout/gestureviewer.xml
index 73d6a35..e4cca52 100755
--- a/tests/sketch/res/layout/gestureviewer.xml
+++ b/tests/sketch/res/layout/gestureviewer.xml
@@ -17,7 +17,7 @@
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:orientation="vertical"
     android:layout_width="fill_parent"
-    android:layout_height="wrap_content">
+    android:layout_height="fill_parent">
     
     <Spinner 
         android:id="@+id/spinner"
@@ -26,11 +26,11 @@
         android:drawSelectorOnTop="true"
         android:prompt="@string/recognition_result"/>
     
-    <com.android.gesture.GestureOverlay 
+    <android.gesture.GestureOverlayView
         android:id="@+id/drawingpad"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
-        android:layout_weight="1"/>
+        android:layout_weight="1" />
 
     <LinearLayout 
         android:orientation="horizontal"
diff --git a/tests/sketch/res/layout/overlaydemo.xml b/tests/sketch/res/layout/overlaydemo.xml
index b6bbab3..4d5a657 100644
--- a/tests/sketch/res/layout/overlaydemo.xml
+++ b/tests/sketch/res/layout/overlaydemo.xml
@@ -1,12 +1,27 @@
 <?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
+<!-- Copyright (C) 2009 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<android.gesture.GestureOverlayView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/overlay"
     android:layout_width="fill_parent"
-    android:layout_height="fill_parent"
-    >
+    android:layout_height="fill_parent">
+
     <ListView
-      android:id="@+id/list" 
-      android:layout_width="fill_parent" 
-      android:layout_height="0dip"
-      android:layout_weight="1"/>
-</LinearLayout>
+        android:id="@+id/list"
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent" />
+
+</android.gesture.GestureOverlayView>
diff --git a/tests/sketch/src/com/android/gesture/GestureConstants.java b/tests/sketch/src/com/android/gesture/GestureConstants.java
deleted file mode 100644
index cb64791..0000000
--- a/tests/sketch/src/com/android/gesture/GestureConstants.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.gesture;
-
-interface GestureConstants {
-    static final String XML_TAG_LIBRARY = "library";
-    static final String XML_TAG_ENTRY = "entry";
-    static final String XML_TAG_GESTURE = "gesture";
-    static final String XML_TAG_STROKE = "stroke";
-    static final String XML_TAG_ID = "id";
-    static final String XML_TAG_NAME = "name";
-    static final String STRING_GESTURE_DELIIMITER = "#";
-    static final String STRING_STROKE_DELIIMITER = ",";
-    static final int STROKE_STRING_BUFFER_SIZE = 1024;
-    static final int STROKE_POINT_BUFFER_SIZE = 100; // number of points
-    static final int IO_BUFFER_SIZE = 8 * 1024; // 8K
-    String LOG_TAG = "GestureLibrary";
-}
diff --git a/tests/sketch/src/com/android/gesture/GestureLibrary.java b/tests/sketch/src/com/android/gesture/GestureLibrary.java
deleted file mode 100644
index 3e753e7..0000000
--- a/tests/sketch/src/com/android/gesture/GestureLibrary.java
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- * Copyright (C) 2008-2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.gesture;
-
-import android.util.Config;
-import android.util.Log;
-import android.util.Xml;
-import android.util.Xml.Encoding;
-
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.Locator;
-import org.xml.sax.SAXException;
-import org.xmlpull.v1.XmlSerializer;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Set;
-
-import static com.android.gesture.GestureConstants.LOG_TAG;
-
-/**
- * GestureLibrary maintains gesture examples and makes predictions on a new
- * gesture
- */
-public class GestureLibrary {
-
-    private static final String NAMESPACE = "";
-
-    public static final int SEQUENCE_INVARIANT = 1;
-    // when SEQUENCE_SENSITIVE is used, only single stroke gestures are allowed
-    public static final int SEQUENCE_SENSITIVE = 2;
-
-    public static final int ORIENTATION_INVARIANT = 1;
-    // ORIENTATION_SENSITIVE is only available for single stroke gestures
-    public static final int ORIENTATION_SENSITIVE = 2;
-
-    private int mSequenceType = SEQUENCE_SENSITIVE;
-    private int mOrientationStyle = ORIENTATION_SENSITIVE;
-
-    private final String mGestureFileName;
-
-    private final HashMap<String, ArrayList<Gesture>> mEntryName2gestures =
-            new HashMap<String, ArrayList<Gesture>>();
-
-    private Learner mClassifier;
-
-    private boolean mChanged = false;
-
-    /**
-     * @param path where gesture data is stored
-     */
-    public GestureLibrary(String path) {
-        mGestureFileName = path;
-        mClassifier = new InstanceLearner();
-    }
-
-    /**
-     * Specify whether the gesture library will handle orientation sensitive
-     * gestures. Use ORIENTATION_INVARIANT or ORIENTATION_SENSITIVE
-     * 
-     * @param style
-     */
-    public void setOrientationStyle(int style) {
-        mOrientationStyle = style;
-    }
-
-    public int getOrientationStyle() {
-        return mOrientationStyle;
-    }
-
-    public void setGestureType(int type) {
-        mSequenceType = type;
-    }
-
-    public int getGestureType() {
-        return mSequenceType;
-    }
-
-    /**
-     * Get all the gesture entry names in the library
-     * 
-     * @return a set of strings
-     */
-    public Set<String> getGestureEntries() {
-        return mEntryName2gestures.keySet();
-    }
-
-    /**
-     * Recognize a gesture
-     * 
-     * @param gesture the query
-     * @return a list of predictions of possible entries for a given gesture
-     */
-    public ArrayList<Prediction> recognize(Gesture gesture) {
-        Instance instance = Instance.createInstance(this, gesture, null);
-        return mClassifier.classify(this, instance);
-    }
-
-    /**
-     * Add a gesture for the entry
-     * 
-     * @param entryName entry name
-     * @param gesture
-     */
-    public void addGesture(String entryName, Gesture gesture) {
-        if (entryName == null || entryName.length() == 0) {
-            return;
-        }
-        ArrayList<Gesture> gestures = mEntryName2gestures.get(entryName);
-        if (gestures == null) {
-            gestures = new ArrayList<Gesture>();
-            mEntryName2gestures.put(entryName, gestures);
-        }
-        gestures.add(gesture);
-        mClassifier.addInstance(Instance.createInstance(this, gesture, entryName));
-        mChanged = true;
-    }
-
-    /**
-     * Remove a gesture from the library. If there are no more gestures for the
-     * given entry, the gesture entry will be removed.
-     * 
-     * @param entryName entry name
-     * @param gesture
-     */
-    public void removeGesture(String entryName, Gesture gesture) {
-        ArrayList<Gesture> gestures = mEntryName2gestures.get(entryName);
-        if (gestures == null) {
-            return;
-        }
-
-        gestures.remove(gesture);
-
-        // if there are no more samples, remove the entry automatically
-        if (gestures.isEmpty()) {
-            mEntryName2gestures.remove(entryName);
-        }
-
-        mClassifier.removeInstance(gesture.getID());
-
-        mChanged = true;
-    }
-
-    /**
-     * Remove a entry of gestures
-     * 
-     * @param entryName the entry name
-     */
-    public void removeEntireEntry(String entryName) {
-        mEntryName2gestures.remove(entryName);
-        mClassifier.removeInstances(entryName);
-        mChanged = true;
-    }
-
-    /**
-     * Get all the gestures of an entry
-     * 
-     * @param entryName
-     * @return the list of gestures that is under this name
-     */
-    public ArrayList<Gesture> getGestures(String entryName) {
-        ArrayList<Gesture> gestures = mEntryName2gestures.get(entryName);
-        if (gestures != null) {
-            return new ArrayList<Gesture>(gestures);
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * Save the gesture library
-     */
-    public boolean save() {
-        if (!mChanged) {
-            return true;
-        }
-
-        boolean result= false;
-        PrintWriter writer = null;
-
-        try {
-            File file = new File(mGestureFileName);
-            if (!file.getParentFile().exists()) {
-                if (!file.getParentFile().mkdirs()) {
-                    return false;
-                }
-            }
-
-            writer = new PrintWriter(new BufferedOutputStream(new FileOutputStream(
-                    mGestureFileName), GestureConstants.IO_BUFFER_SIZE));
-
-            final XmlSerializer serializer = Xml.newSerializer();
-            serializer.setOutput(writer);
-            serializer.startDocument(Encoding.ISO_8859_1.name(), null);
-            serializer.startTag(NAMESPACE, GestureConstants.XML_TAG_LIBRARY);
-
-            final HashMap<String, ArrayList<Gesture>> maps = mEntryName2gestures;
-
-            for (String key : maps.keySet()) {
-                ArrayList<Gesture> examples = maps.get(key);
-                // save an entry
-                serializer.startTag(NAMESPACE, GestureConstants.XML_TAG_ENTRY);
-                serializer.attribute(NAMESPACE, GestureConstants.XML_TAG_NAME, key);
-                int count = examples.size();
-                for (int i = 0; i < count; i++) {
-                    Gesture gesture = examples.get(i);
-                    // save each gesture in the entry
-                    gesture.toXML(NAMESPACE, serializer);
-                }
-                serializer.endTag(NAMESPACE, GestureConstants.XML_TAG_ENTRY);
-            }
-
-            serializer.endTag(NAMESPACE, GestureConstants.XML_TAG_LIBRARY);
-            serializer.endDocument();
-            serializer.flush();
-
-            mChanged = false;
-            result = true;
-        } catch (IOException ex) {
-            Log.d(LOG_TAG, "Failed to save gestures:", ex);
-        } finally {
-            GestureUtilities.closeStream(writer);
-        }
-
-        return result;
-    }
-
-    /**
-     * Load the gesture library
-     */
-    public boolean load() {
-        boolean result = false;
-
-        final File file = new File(mGestureFileName);
-        if (file.exists()) {
-            BufferedInputStream in = null;
-            try {
-                if (Config.DEBUG) {
-                    Log.v(LOG_TAG, "Load from " + mGestureFileName);
-                }
-                in = new BufferedInputStream(new FileInputStream(
-                        mGestureFileName), GestureConstants.IO_BUFFER_SIZE);
-                Xml.parse(in, Encoding.ISO_8859_1, new CompactInkHandler());
-                result = true;
-            } catch (SAXException ex) {
-                Log.d(LOG_TAG, "Failed to load gestures:", ex);
-            } catch (IOException ex) {
-                Log.d(LOG_TAG, "Failed to load gestures:", ex);
-            } finally {
-                GestureUtilities.closeStream(in);
-            }
-        }
-
-        return result;
-    }
-
-    private class CompactInkHandler implements ContentHandler {
-        final StringBuilder mBuffer = new StringBuilder(GestureConstants.STROKE_STRING_BUFFER_SIZE);
-
-        String mEntryName;
-
-        Gesture mCurrentGesture = null;
-        ArrayList<Gesture> mGestures;
-
-        CompactInkHandler() {
-        }
-
-        public void characters(char[] ch, int start, int length) {
-            mBuffer.append(ch, start, length);
-        }
-
-        public void endDocument() {
-        }
-
-        public void endElement(String uri, String localName, String qName) {
-            if (localName.equals(GestureConstants.XML_TAG_ENTRY)) {
-                mEntryName2gestures.put(mEntryName, mGestures);
-                mGestures = null;
-            } else if (localName.equals(GestureConstants.XML_TAG_GESTURE)) {
-                mGestures.add(mCurrentGesture);
-                mClassifier.addInstance(Instance.createInstance(GestureLibrary.this,
-                        mCurrentGesture, mEntryName));
-                mCurrentGesture = null;
-            } else if (localName.equals(GestureConstants.XML_TAG_STROKE)) {
-                mCurrentGesture.addStroke(GestureStroke.createFromString(mBuffer.toString()));
-                mBuffer.setLength(0);
-            }
-        }
-
-        public void endPrefixMapping(String prefix) {
-        }
-
-        public void ignorableWhitespace(char[] ch, int start, int length) {
-        }
-
-        public void processingInstruction(String target, String data) {
-        }
-
-        public void setDocumentLocator(Locator locator) {
-        }
-
-        public void skippedEntity(String name) {
-        }
-
-        public void startDocument() {
-        }
-
-        public void startElement(String uri, String localName, String qName, Attributes attributes) {
-            if (localName.equals(GestureConstants.XML_TAG_ENTRY)) {
-                mGestures = new ArrayList<Gesture>();
-                mEntryName = attributes.getValue(NAMESPACE, GestureConstants.XML_TAG_NAME);
-            } else if (localName.equals(GestureConstants.XML_TAG_GESTURE)) {
-                mCurrentGesture = new Gesture();
-                mCurrentGesture.setID(Long.parseLong(attributes.getValue(NAMESPACE,
-                        GestureConstants.XML_TAG_ID)));
-            }
-        }
-
-        public void startPrefixMapping(String prefix, String uri) {
-        }
-    }
-}
diff --git a/tests/sketch/src/com/android/gesture/GestureListener.java b/tests/sketch/src/com/android/gesture/GestureListener.java
deleted file mode 100755
index 9b50714..0000000
--- a/tests/sketch/src/com/android/gesture/GestureListener.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2008-2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.gesture;
-
-import android.view.MotionEvent;
-
-/**
- * An interface for processing gesture events
- */
-public interface GestureListener {
-    public void onStartGesture(GestureOverlay overlay, MotionEvent event);
-
-    public void onGesture(GestureOverlay overlay, MotionEvent event);
-
-    public void onFinishGesture(GestureOverlay overlay, MotionEvent event);
-}
diff --git a/tests/sketch/src/com/android/gesture/GestureOverlay.java b/tests/sketch/src/com/android/gesture/GestureOverlay.java
deleted file mode 100755
index 454cecb..0000000
--- a/tests/sketch/src/com/android/gesture/GestureOverlay.java
+++ /dev/null
@@ -1,390 +0,0 @@
-/*
- * Copyright (C) 2008-2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.gesture;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.BlurMaskFilter;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.Rect;
-import android.os.Handler;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.view.View;
-
-import java.util.ArrayList;
-
-/**
- * A (transparent) overlay for gesture input that can be placed on top of other
- * widgets. The view can also be opaque.
- */
-
-public class GestureOverlay extends View {
-    static final float TOUCH_TOLERANCE = 3;
-
-    // TODO: Move all these values into XML attributes
-    private static final int TRANSPARENT_BACKGROUND = 0x00000000;
-
-    // TODO: SHOULD BE A TOTAL DURATION
-    private static final float FADING_ALPHA_CHANGE = 0.15f;
-    private static final long FADING_OFFSET = 300;
-    private static final long FADING_REFRESHING_RATE = 16;
-
-    private static final int GESTURE_STROKE_WIDTH = 12;
-    private static final boolean GESTURE_RENDERING_ANTIALIAS = true;
-
-    private static final boolean DITHER_FLAG = true;
-
-    public static final int DEFAULT_GESTURE_COLOR = 0xFFFFFF00;
-
-    private static final int REFRESH_RANGE = 10;
-
-    private static final BlurMaskFilter BLUR_MASK_FILTER =
-            new BlurMaskFilter(1, BlurMaskFilter.Blur.NORMAL);
-    
-
-    // double buffering
-    private Paint mGesturePaint;
-
-    private final Paint mBitmapPaint = new Paint(Paint.DITHER_FLAG);
-    private Bitmap mBitmap; // with transparent background
-    private Canvas mBitmapCanvas;
-
-    // for rendering immediate ink feedback
-    private Rect mInvalidRect = new Rect();
-
-    private Path mPath;
-
-    private float mX;
-    private float mY;
-    
-    private float mCurveEndX;
-    private float mCurveEndY;
-
-    // current gesture
-    private Gesture mCurrentGesture = null;
-
-    // TODO: Make this a list of WeakReferences
-    private final ArrayList<GestureListener> mGestureListeners = new ArrayList<GestureListener>();
-    private ArrayList<GesturePoint> mPointBuffer = null;
-
-    // fading out effect
-    private boolean mIsFadingOut = false;
-    private float mFadingAlpha = 1;
-
-    private Handler mHandler = new Handler();
-
-    private final Runnable mFadingOut = new Runnable() {
-        public void run() {
-            if (mIsFadingOut) {
-                mFadingAlpha -= FADING_ALPHA_CHANGE;
-                if (mFadingAlpha <= 0) {
-                    mIsFadingOut = false;
-                    mPath = null;
-                    mCurrentGesture = null;
-                    mBitmap.eraseColor(TRANSPARENT_BACKGROUND);
-                } else {
-                    mHandler.postDelayed(this, FADING_REFRESHING_RATE);
-                }
-                invalidate();
-            }
-        }
-    };
-
-    public GestureOverlay(Context context) {
-        super(context);
-        init();
-    }
-
-    public GestureOverlay(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        init();
-    }
-
-    public ArrayList<GesturePoint> getCurrentStroke() {
-        return mPointBuffer;
-    }
-
-    public Gesture getCurrentGesture() {
-        return mCurrentGesture;
-    }
-
-    /**
-     * Set Gesture color
-     * 
-     * @param color
-     */
-    public void setGestureColor(int color) {
-        mGesturePaint.setColor(color);
-        if (mCurrentGesture != null) {
-            mBitmap.eraseColor(TRANSPARENT_BACKGROUND);
-            mCurrentGesture.draw(mBitmapCanvas, mGesturePaint);
-        }
-    }
-
-    /**
-     * Set the gesture to be shown in the view
-     * 
-     * @param gesture
-     */
-    public void setCurrentGesture(Gesture gesture) {
-        if (mCurrentGesture != null) {
-            clear(false);
-        }
-
-        mCurrentGesture = gesture;
-
-        if (gesture != null) {
-            if (mBitmapCanvas != null) {
-                gesture.draw(mBitmapCanvas, mGesturePaint);
-                invalidate();
-            }
-        }
-    }
-
-    private void init() {
-        mGesturePaint = new Paint();
-
-        final Paint gesturePaint = mGesturePaint;
-        gesturePaint.setAntiAlias(GESTURE_RENDERING_ANTIALIAS);
-        gesturePaint.setColor(DEFAULT_GESTURE_COLOR);
-        gesturePaint.setStyle(Paint.Style.STROKE);
-        gesturePaint.setStrokeJoin(Paint.Join.ROUND);
-        gesturePaint.setStrokeCap(Paint.Cap.ROUND);
-        gesturePaint.setStrokeWidth(GESTURE_STROKE_WIDTH);
-        gesturePaint.setDither(DITHER_FLAG);
-
-        mPath = null;
-    }
-
-    @Override
-    protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
-        super.onSizeChanged(width, height, oldWidth, oldHeight);
-
-        if (width <= 0 || height <= 0) {
-            return;
-        }
-
-        int targetWidth = width > oldWidth ? width : oldWidth;
-        int targetHeight = height > oldHeight ? height : oldHeight;
-
-        if (mBitmap != null) mBitmap.recycle();
-
-        mBitmap = Bitmap.createBitmap(targetWidth, targetHeight, Bitmap.Config.ARGB_8888);
-        if (mBitmapCanvas != null) {
-            mBitmapCanvas.setBitmap(mBitmap);
-        } else {
-            mBitmapCanvas = new Canvas(mBitmap);
-        }
-        mBitmapCanvas.drawColor(TRANSPARENT_BACKGROUND);
-
-        if (mCurrentGesture != null) {
-            mCurrentGesture.draw(mBitmapCanvas, mGesturePaint);
-        }
-    }
-
-    public void addGestureListener(GestureListener listener) {
-        mGestureListeners.add(listener);
-    }
-
-    public void removeGestureListener(GestureListener listener) {
-        mGestureListeners.remove(listener);
-    }
-
-    @Override
-    protected void onDraw(Canvas canvas) {
-        super.onDraw(canvas);
-
-        // draw double buffer
-        if (mIsFadingOut) {
-            mBitmapPaint.setAlpha((int) (255 * mFadingAlpha));
-            canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
-        } else {
-            mBitmapPaint.setAlpha(255);
-            canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
-        }
-
-        // draw the current stroke
-        if (mPath != null) {
-            canvas.drawPath(mPath, mGesturePaint);
-        }
-    }
-
-    /**
-     * Clear up the overlay
-     * 
-     * @param fadeOut whether the gesture on the overlay should fade out
-     *            gradually or disappear immediately
-     */
-    public void clear(boolean fadeOut) {
-        if (fadeOut) {
-            mFadingAlpha = 1;
-            mIsFadingOut = true;
-            mHandler.removeCallbacks(mFadingOut);
-            mHandler.postDelayed(mFadingOut, FADING_OFFSET);
-        } else {
-            mPath = null;
-            mCurrentGesture = null;
-            if (mBitmap != null) {
-                mBitmap.eraseColor(TRANSPARENT_BACKGROUND);
-                invalidate();
-            }
-        }
-    }
-
-    public void cancelFadingOut() {
-        mIsFadingOut = false;
-        mHandler.removeCallbacks(mFadingOut);
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        if (!isEnabled()) {
-            return true;
-        }
-
-        switch (event.getAction()) {
-            case MotionEvent.ACTION_DOWN:
-                Rect rect = touchStart(event);
-                invalidate(rect);
-                break;
-            case MotionEvent.ACTION_MOVE:
-                rect = touchMove(event);
-                if (rect != null) {
-                    invalidate(rect);
-                }
-                break;
-            case MotionEvent.ACTION_UP:
-                touchUp(event);
-                invalidate();
-                break;
-        }
-
-        return true;
-    }
-
-    private Rect touchStart(MotionEvent event) {
-        // pass the event to handlers
-        final ArrayList<GestureListener> listeners = mGestureListeners;
-        final int count = listeners.size();
-        for (int i = 0; i < count; i++) {
-            GestureListener listener = listeners.get(i);
-            listener.onStartGesture(this, event);
-        }
-
-        // if there is fading out going on, stop it.
-        if (mIsFadingOut) {
-            mIsFadingOut = false;
-            mHandler.removeCallbacks(mFadingOut);
-            mBitmap.eraseColor(TRANSPARENT_BACKGROUND);
-            mCurrentGesture = null;
-        }
-
-        float x = event.getX();
-        float y = event.getY();
-
-        mX = x;
-        mY = y;
-
-        if (mCurrentGesture == null) {
-            mCurrentGesture = new Gesture();
-        }
-
-        mPointBuffer = new ArrayList<GesturePoint>();
-        mPointBuffer.add(new GesturePoint(x, y, event.getEventTime()));
-
-        mPath = new Path();
-        mPath.moveTo(x, y);
-
-        mInvalidRect.set((int) x - REFRESH_RANGE, (int) y - REFRESH_RANGE,
-                (int) x + REFRESH_RANGE, (int) y + REFRESH_RANGE);
-        
-        mCurveEndX = x;
-        mCurveEndY = y;
-        
-        return mInvalidRect;
-    }
-
-    private Rect touchMove(MotionEvent event) {
-        Rect areaToRefresh = null;
-        
-        float x = event.getX();
-        float y = event.getY();
-
-        float dx = Math.abs(x - mX);
-        float dy = Math.abs(y - mY);
-        
-        if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
-            
-            // start with the curve end
-            mInvalidRect.set((int) mCurveEndX - REFRESH_RANGE, (int) mCurveEndY - REFRESH_RANGE,
-                    (int) mCurveEndX + REFRESH_RANGE, (int) mCurveEndY + REFRESH_RANGE);
-            
-            mCurveEndX  = (x + mX) / 2;
-            mCurveEndY = (y + mY) / 2;
-            mPath.quadTo(mX, mY, mCurveEndX, mCurveEndY);
-            
-            // union with the control point of the new curve
-            mInvalidRect.union((int) mX - REFRESH_RANGE, (int) mY - REFRESH_RANGE,
-                    (int) mX + REFRESH_RANGE, (int) mY + REFRESH_RANGE);
-            
-            // union with the end point of the new curve
-            mInvalidRect.union((int) mCurveEndX - REFRESH_RANGE, (int) mCurveEndY - REFRESH_RANGE,
-                    (int) mCurveEndX + REFRESH_RANGE, (int) mCurveEndY + REFRESH_RANGE);
-
-            areaToRefresh = mInvalidRect;
-            
-            mX = x;
-            mY = y;
-        }
-        
-
-        mPointBuffer.add(new GesturePoint(x, y, event.getEventTime()));
-
-        // pass the event to handlers
-        final ArrayList<GestureListener> listeners = mGestureListeners;
-        final int count = listeners.size();
-        for (int i = 0; i < count; i++) {
-            listeners.get(i).onGesture(this, event);
-        }
-        
-        return areaToRefresh;
-    }
-
-    private void touchUp(MotionEvent event) {
-        // add the stroke to the current gesture
-        mCurrentGesture.addStroke(new GestureStroke(mPointBuffer));
-
-        // add the stroke to the double buffer
-        mGesturePaint.setMaskFilter(BLUR_MASK_FILTER);
-        mBitmapCanvas.drawPath(mPath, mGesturePaint);
-        mGesturePaint.setMaskFilter(null);
-        
-        // pass the event to handlers
-        final ArrayList<GestureListener> listeners = mGestureListeners;
-        final int count = listeners.size();
-        for (int i = 0; i < count; i++) {
-            listeners.get(i).onFinishGesture(this, event);
-        }
-        
-        mPath = null;        
-        mPointBuffer = null;
-    }
-
-}
diff --git a/tests/sketch/src/com/android/gesture/GestureStroke.java b/tests/sketch/src/com/android/gesture/GestureStroke.java
deleted file mode 100644
index 3555010..0000000
--- a/tests/sketch/src/com/android/gesture/GestureStroke.java
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright (C) 2008-2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.gesture;
-
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.RectF;
-
-import org.xmlpull.v1.XmlSerializer;
-
-import java.io.IOException;
-import java.util.ArrayList;
-
-/**
- * A gesture stroke started on a touch down and ended on a touch up.
- */
-public class GestureStroke {
-    public final RectF boundingBox;
-
-    public final float length;
-    public final float[] points;
-
-    private final long[] timestamps;
-    private Path mCachedPath;
-
-    /**
-     * Construct a gesture stroke from a list of gesture points
-     * 
-     * @param points
-     */
-    public GestureStroke(ArrayList<GesturePoint> points) {
-        final int count = points.size();
-        final float[] tmpPoints = new float[count * 2];
-        final long[] times = new long[count];
-
-        RectF bx = null;
-        float len = 0;
-        int index = 0;
-
-        for (int i = 0; i < count; i++) {
-            final GesturePoint p = points.get(i);
-            tmpPoints[i * 2] = p.x;
-            tmpPoints[i * 2 + 1] = p.y;
-            times[index] = p.timestamp;
-
-            if (bx == null) {
-                bx = new RectF();
-                bx.top = p.y;
-                bx.left = p.x;
-                bx.right = p.x;
-                bx.bottom = p.y;
-                len = 0;
-            } else {
-                len += Math.sqrt(Math.pow(p.x - tmpPoints[(i - 1) * 2], 2)
-                        + Math.pow(p.y - tmpPoints[(i -1 ) * 2 + 1], 2));
-                bx.union(p.x, p.y);
-            }
-            index++;
-        }
-        
-        timestamps = times;
-        this.points = tmpPoints;
-        boundingBox = bx;
-        length = len;
-    }
-
-    /**
-     * Draw the gesture with a given canvas and paint
-     * 
-     * @param canvas
-     */
-    void draw(Canvas canvas, Paint paint) {
-        if (mCachedPath == null) {
-            final float[] localPoints = points;
-            final int count = localPoints.length;
-
-            Path path = null;
-
-            float mX = 0;
-            float mY = 0;
-
-            for (int i = 0; i < count; i += 2) {
-                float x = localPoints[i];
-                float y = localPoints[i + 1];
-                if (path == null) {
-                    path = new Path();
-                    path.moveTo(x, y);
-                    mX = x;
-                    mY = y;
-                } else {
-                    float dx = Math.abs(x - mX);
-                    float dy = Math.abs(y - mY);
-                    if (dx >= 3 || dy >= 3) {
-                        path.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
-                        mX = x;
-                        mY = y;
-                    }
-                }
-            }
-
-            mCachedPath = path;
-        }
-
-        canvas.drawPath(mCachedPath, paint);
-    }
-
-    /**
-     * Convert the stroke to a Path based on the number of points
-     * 
-     * @param width the width of the bounding box of the target path
-     * @param height the height of the bounding box of the target path
-     * @param numSample the number of points needed
-     * @return the path
-     */
-    public Path toPath(float width, float height, int numSample) {
-        final float[] pts = GestureUtilities.temporalSampling(this, numSample);
-        final RectF rect = boundingBox;
-        final float scale = height / rect.height();
-
-        final Matrix matrix = new Matrix();
-        matrix.setTranslate(-rect.left, -rect.top);
-        matrix.postScale(scale, scale);
-        matrix.mapPoints(pts);
-
-        float mX = 0;
-        float mY = 0;
-
-        Path path = null;
-
-        final int count = pts.length;
-
-        for (int i = 0; i < count; i += 2) {
-            float x = pts[i];
-            float y = pts[i + 1];
-            if (path == null) {
-                path = new Path();
-                path.moveTo(x, y);
-                mX = x;
-                mY = y;
-            } else {
-                float dx = Math.abs(x - mX);
-                float dy = Math.abs(y - mY);
-                if (dx >= GestureOverlay.TOUCH_TOLERANCE || dy >= GestureOverlay.TOUCH_TOLERANCE) {
-                    path.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
-                    mX = x;
-                    mY = y;
-                }
-            }
-        }
-
-        return path;
-    }
-
-    /**
-     * Save the gesture stroke as XML
-     * 
-     * @param namespace
-     * @param serializer
-     * @throws IOException
-     */
-    void toXML(String namespace, XmlSerializer serializer) throws IOException {
-        serializer.startTag(namespace, GestureConstants.XML_TAG_STROKE);
-        serializer.text(toString());
-        serializer.endTag(namespace, GestureConstants.XML_TAG_STROKE);
-    }
-
-    /**
-     * Create a gesture stroke from a string
-     * 
-     * @param str
-     * @return the gesture stroke
-     */
-    public static GestureStroke createFromString(String str) {
-        final ArrayList<GesturePoint> points = new ArrayList<GesturePoint>(
-                GestureConstants.STROKE_POINT_BUFFER_SIZE);
-
-        int endIndex;
-        int startIndex = 0;
-
-        while ((endIndex =
-                str.indexOf(GestureConstants.STRING_STROKE_DELIIMITER, startIndex + 1)) != -1) {
-
-            // parse x
-            String token = str.substring(startIndex, endIndex);
-            float x = Float.parseFloat(token);
-            startIndex = endIndex + 1;
-
-            // parse y
-            endIndex = str.indexOf(GestureConstants.STRING_STROKE_DELIIMITER, startIndex + 1);
-            token = str.substring(startIndex, endIndex);
-            float y = Float.parseFloat(token);
-            startIndex = endIndex + 1;
-
-            // parse t
-            endIndex = str.indexOf(GestureConstants.STRING_STROKE_DELIIMITER, startIndex + 1);
-            token = str.substring(startIndex, endIndex);
-            long time = Long.parseLong(token);
-            startIndex = endIndex + 1;
-
-            points.add(new GesturePoint(x, y, time));
-        }
-
-        return new GestureStroke(points);
-    }
-
-    /**
-     * Convert the stroke to string
-     */
-    @Override
-    public String toString() {
-        final StringBuilder str = new StringBuilder(GestureConstants.STROKE_STRING_BUFFER_SIZE);
-        final float[] pts = points;
-        final long[] times = timestamps;
-        final int count = points.length;
-
-        for (int i = 0; i < count; i += 2) {
-            str.append(pts[i]).append(GestureConstants.STRING_STROKE_DELIIMITER);
-            str.append(pts[i + 1]).append(GestureConstants.STRING_STROKE_DELIIMITER);
-            str.append(times[i / 2]).append(GestureConstants.STRING_STROKE_DELIIMITER);
-        }
-
-        return str.toString();
-    }
-
-    /**
-     * Invalidate the cached path that is used for rendering the stroke
-     */
-    public void invalidate() {
-        mCachedPath = null;
-    }
-}
diff --git a/tests/sketch/src/com/android/gesture/LetterRecognizer.java b/tests/sketch/src/com/android/gesture/LetterRecognizer.java
deleted file mode 100644
index 73151de5..0000000
--- a/tests/sketch/src/com/android/gesture/LetterRecognizer.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.gesture;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.util.Log;
-
-import java.io.IOException;
-import java.io.DataInputStream;
-import java.io.BufferedInputStream;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-
-public class LetterRecognizer {
-    private static final String LOG_TAG = "LetterRecognizer";
-
-    public final static int LATIN_LOWERCASE = 0;
-
-    private SigmoidUnit[] mHiddenLayer;
-    private SigmoidUnit[] mOutputLayer;
-
-    private final String[] mClasses;
-
-    private final int mInputCount;
-
-    private static class SigmoidUnit {
-        final float[] mWeights;
-
-        SigmoidUnit(float[] weights) {
-            mWeights = weights;
-        }
-
-        private float compute(float[] inputs) {
-            float sum = 0;
-
-            final int count = inputs.length;
-            final float[] weights = mWeights;
-
-            for (int i = 0; i < count; i++) {
-                sum += inputs[i] * weights[i];
-            }
-            sum += weights[weights.length - 1];
-
-            return 1.0f / (float) (1 + Math.exp(-sum));
-        }
-    }
-
-    private LetterRecognizer(int numOfInput, int numOfHidden, String[] classes) {
-        mInputCount = (int)Math.sqrt(numOfInput);
-        mHiddenLayer = new SigmoidUnit[numOfHidden];
-        mClasses = classes;
-        mOutputLayer = new SigmoidUnit[classes.length];
-    }
-
-    public static LetterRecognizer getLetterRecognizer(Context context, int type) {
-        switch (type) {
-            case LATIN_LOWERCASE: {
-                return createFromResource(context, com.android.internal.R.raw.latin_lowercase);
-            }
-        }
-        return null;
-    }
-
-    public ArrayList<Prediction> recognize(Gesture gesture) {
-        return classify(GestureUtilities.spatialSampling(gesture, mInputCount));
-    }
-
-    private ArrayList<Prediction> classify(float[] vector) {
-        final float[] intermediateOutput = compute(mHiddenLayer, vector);
-        final float[] output = compute(mOutputLayer, intermediateOutput);
-        final ArrayList<Prediction> predictions = new ArrayList<Prediction>();
-
-        double sum = 0;
-
-        final String[] classes = mClasses;
-        final int count = classes.length;
-
-        for (int i = 0; i < count; i++) {
-            double score = output[i];
-            sum += score;
-            predictions.add(new Prediction(classes[i], score));
-        }
-
-        for (int i = 0; i < count; i++) {
-            predictions.get(i).score /= sum;
-        }
-
-        Collections.sort(predictions, new Comparator<Prediction>() {
-            public int compare(Prediction object1, Prediction object2) {
-                double score1 = object1.score;
-                double score2 = object2.score;
-                if (score1 > score2) {
-                    return -1;
-                } else if (score1 < score2) {
-                    return 1;
-                } else {
-                    return 0;
-                }
-            }
-        });
-        return predictions;
-    }
-
-    private float[] compute(SigmoidUnit[] layer, float[] input) {
-        final float[] output = new float[layer.length];
-        final int count = layer.length;
-
-        for (int i = 0; i < count; i++) {
-            output[i] = layer[i].compute(input);
-        }
-
-        return output;
-    }
-
-    private static LetterRecognizer createFromResource(Context context, int resourceID) {
-        final Resources resources = context.getResources();
-
-        DataInputStream in = null;
-        LetterRecognizer classifier = null;
-
-        try {
-            in = new DataInputStream(new BufferedInputStream(resources.openRawResource(resourceID)));
-
-            final int iCount = in.readInt();
-            final int hCount = in.readInt();
-            final int oCount = in.readInt();
-
-            final String[] classes = new String[oCount];
-            for (int i = 0; i < classes.length; i++) {
-                classes[i] = in.readUTF();
-            }
-
-            classifier = new LetterRecognizer(iCount, hCount, classes);
-            SigmoidUnit[] hiddenLayer = new SigmoidUnit[hCount];
-            SigmoidUnit[] outputLayer = new SigmoidUnit[oCount];
-
-            for (int i = 0; i < hCount; i++) {
-                float[] weights = new float[iCount];
-                for (int j = 0; j < iCount; j++) {
-                    weights[j] = in.readFloat();
-                }
-                hiddenLayer[i] = new SigmoidUnit(weights);
-            }
-
-            for (int i = 0; i < oCount; i++) {
-                float[] weights = new float[hCount];
-                for (int j = 0; j < hCount; j++) {
-                    weights[j] = in.readFloat();
-                }
-                outputLayer[i] = new SigmoidUnit(weights);
-            }
-
-            classifier.mHiddenLayer = hiddenLayer;
-            classifier.mOutputLayer = outputLayer;
-
-        } catch (IOException e) {
-            Log.d(LOG_TAG, "Failed to load gestures:", e);
-        } finally {
-            GestureUtilities.closeStream(in);
-        }
-
-        return classifier;
-    }
-}
diff --git a/tests/sketch/src/com/android/gesture/TouchThroughGesturing.java b/tests/sketch/src/com/android/gesture/TouchThroughGesturing.java
deleted file mode 100644
index fc878c8..0000000
--- a/tests/sketch/src/com/android/gesture/TouchThroughGesturing.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * Copyright (C) 2008-2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.gesture;
-
-import android.graphics.Color;
-import android.view.MotionEvent;
-import android.view.View;
-
-import java.util.ArrayList;
-
-/**
- * TouchThroughGesturing implements the interaction behavior that allows a user
- * to gesture over a regular UI widget such as ListView and at the same time,
- * still allows a user to perform basic interactions (clicking, scrolling and panning) 
- * with the underlying widget.
- */
-
-public class TouchThroughGesturing implements GestureListener {
-    public static final int SINGLE_STROKE = 0;
-    public static final int MULTIPLE_STROKE = 1;
-
-    private static final float STROKE_LENGTH_THRESHOLD = 30;
-    private static final float SQUARENESS_THRESHOLD = 0.275f;
-    private static final float ANGLE_THRESHOLD = 40;
-
-    private static final boolean STEAL_EVENTS = false;
-
-    public static final int DEFAULT_UNCERTAIN_GESTURE_COLOR = Color.argb(60, 255, 255, 0);
-
-    private boolean mIsGesturing = false;
-
-    private float mTotalLength;
-
-    private float mX;
-    private float mY;
-
-    // TODO: Use WeakReference?
-    private View mModel;
-
-    private int mGestureType = SINGLE_STROKE;
-    private int mUncertainGestureColor = DEFAULT_UNCERTAIN_GESTURE_COLOR;
-
-    // TODO: Use WeakReferences
-    private final ArrayList<GestureActionListener> mActionListeners =
-            new ArrayList<GestureActionListener>();
-
-    public TouchThroughGesturing(View model) {
-        mModel = model;
-    }
-
-    /**
-     * 
-     * @param type SINGLE_STROKE or MULTIPLE_STROKE
-     */
-    public void setGestureType(int type) {
-        mGestureType = type;
-    }
-    
-    public void setUncertainGestureColor(int color) {
-        mUncertainGestureColor = color;
-    }
-
-    public void onStartGesture(GestureOverlay overlay, MotionEvent event) {
-        if (mGestureType == MULTIPLE_STROKE) {
-            overlay.cancelFadingOut();
-        }
-
-        mX = event.getX();
-        mY = event.getY();
-        mTotalLength = 0;
-        mIsGesturing = false;
-
-        if (mGestureType == SINGLE_STROKE || overlay.getCurrentGesture() == null
-                || overlay.getCurrentGesture().getStrokesCount() == 0) {
-            overlay.setGestureColor(mUncertainGestureColor);
-        }
-
-        mModel.dispatchTouchEvent(event);
-    }
-
-    public void onGesture(GestureOverlay overlay, MotionEvent event) {
-        //noinspection PointlessBooleanExpression
-        if (!STEAL_EVENTS) {
-            mModel.dispatchTouchEvent(event);
-        }
-
-        if (mIsGesturing) {
-            return;
-        }
-
-        final float x = event.getX();
-        final float y = event.getY();
-        final float dx = x - mX;
-        final float dy = y - mY;
-
-        mTotalLength += (float)Math.sqrt(dx * dx + dy * dy);
-        mX = x;
-        mY = y;
-
-        if (mTotalLength > STROKE_LENGTH_THRESHOLD) {
-            final OrientedBoundingBox box =
-                    GestureUtilities.computeOrientedBoundingBox(overlay.getCurrentStroke());
-            float angle = Math.abs(box.orientation);
-            if (angle > 90) {
-                angle = 180 - angle;
-            }
-            if (box.squareness > SQUARENESS_THRESHOLD || angle < ANGLE_THRESHOLD) {
-                mIsGesturing = true;
-                overlay.setGestureColor(GestureOverlay.DEFAULT_GESTURE_COLOR);
-                if (STEAL_EVENTS) {
-                    event = MotionEvent.obtain(event.getDownTime(), System.currentTimeMillis(),
-                            MotionEvent.ACTION_UP, x, y, event.getPressure(), event.getSize(),
-                            event.getMetaState(), event.getXPrecision(), event.getYPrecision(),
-                            event.getDeviceId(), event.getEdgeFlags());
-                }
-            }
-        }
-
-        if (STEAL_EVENTS) {
-            mModel.dispatchTouchEvent(event);
-        }
-    }
-
-    public void onFinishGesture(GestureOverlay overlay, MotionEvent event) {
-        if (mIsGesturing) {
-            overlay.clear(true);
-
-            final ArrayList<GestureActionListener> listeners = mActionListeners;
-            final int count = listeners.size();
-
-            for (int i = 0; i < count; i++) {
-                listeners.get(i).onGesturePerformed(overlay, overlay.getCurrentGesture());
-            }
-        } else {
-            mModel.dispatchTouchEvent(event);
-            overlay.clear(false);
-        }
-    }
-
-    public void addGestureActionListener(GestureActionListener listener) {
-        mActionListeners.add(listener);
-    }
-
-    public void removeGestureActionListener(GestureActionListener listener) {
-        mActionListeners.remove(listener);
-    }
-
-    public boolean isGesturing() {
-        return mIsGesturing;
-    }
-}
diff --git a/tests/sketch/src/com/android/gesture/example/ContactListGestureOverlay.java b/tests/sketch/src/com/android/gesture/example/ContactListGestureOverlay.java
index 6eb2f23..6767de6 100644
--- a/tests/sketch/src/com/android/gesture/example/ContactListGestureOverlay.java
+++ b/tests/sketch/src/com/android/gesture/example/ContactListGestureOverlay.java
@@ -25,26 +25,20 @@
 import android.provider.Contacts.People;
 import android.util.Log;
 import android.view.View;
-import android.view.ViewGroup;
 import android.view.Window;
 import android.widget.AdapterView;
 import android.widget.ListView;
 
-import com.android.gesture.Gesture;
-import com.android.gesture.GestureActionListener;
-import com.android.gesture.GestureOverlay;
-import com.android.gesture.LetterRecognizer;
-import com.android.gesture.Prediction;
-import com.android.gesture.TouchThroughGesturing;
+import android.gesture.Gesture;
+import android.gesture.GestureOverlayView;
+import android.gesture.LetterRecognizer;
+import android.gesture.Prediction;
 
 import java.util.ArrayList;
 
 public class ContactListGestureOverlay extends Activity {
-
-    private static final String LOGTAG = "ContactListGestureOverlay";
-    
+    private static final String LOG_TAG = "ContactListGestureOverlay";
     private static final String SORT_ORDER = People.DISPLAY_NAME + " COLLATE LOCALIZED ASC";
-
     private static final String[] CONTACTS_PROJECTION = new String[] {
             People._ID, // 0
             People.DISPLAY_NAME, // 1
@@ -52,11 +46,9 @@
 
     private ContactAdapter mContactAdapter;
 
-    private TouchThroughGesturing mGestureProcessor;
-
-    private LetterRecognizer mRecognizer;
-
     private ListView mContactList;
+    private LetterRecognizer mRecognizer;
+    private GestureOverlayView mOverlay;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
@@ -64,10 +56,10 @@
         requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
         setContentView(R.layout.overlaydemo);
 
-        setProgressBarIndeterminateVisibility(true);
-
         // create a letter recognizer
-        mRecognizer = LetterRecognizer.getLetterRecognizer(this, LetterRecognizer.LATIN_LOWERCASE);
+        mRecognizer = LetterRecognizer.getLetterRecognizer(this,
+                LetterRecognizer.RECOGNIZER_LATIN_LOWERCASE);
+        mOverlay = (GestureOverlayView) findViewById(R.id.overlay);
 
         // load the contact list
         mContactList = (ListView) findViewById(R.id.list);
@@ -75,13 +67,14 @@
         mContactList.setTextFilterEnabled(true);
         mContactList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
             public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
-                if (!mGestureProcessor.isGesturing()) {
+                if (!mOverlay.isGesturing()) {
                     Intent intent = new Intent(Intent.ACTION_VIEW, ContentUris.withAppendedId(
                             People.CONTENT_URI, id));
                     startActivity(intent);
                 }
             }
         });
+
         ContentResolver resolver = getContentResolver();
         Cursor cursor = resolver.query(People.CONTENT_URI, CONTACTS_PROJECTION, null, null,
                 SORT_ORDER);
@@ -92,19 +85,17 @@
         mContactAdapter = new ContactAdapter(this, list);
         mContactList.setAdapter(mContactAdapter);
 
-        setProgressBarIndeterminateVisibility(false);
-
-        // add a gesture overlay on top of the ListView
-        GestureOverlay overlay = new GestureOverlay(this);
-        mGestureProcessor = new TouchThroughGesturing(mContactList);
-        mGestureProcessor.setGestureType(TouchThroughGesturing.MULTIPLE_STROKE);
-        mGestureProcessor.addGestureActionListener(new GestureActionListener() {
-            public void onGesturePerformed(GestureOverlay overlay, Gesture gesture) {
+        mOverlay.setGestureStrokeType(GestureOverlayView.GESTURE_STROKE_TYPE_MULTIPLE);
+        mOverlay.addOnGesturePerformedListener(new GestureOverlayView.OnGesturePerformedListener() {
+            public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
                 ArrayList<Prediction> predictions = mRecognizer.recognize(gesture);
                 if (!predictions.isEmpty()) {
-                    Log.v(LOGTAG, "1st Prediction : " + predictions.get(0).name);
-                    Log.v(LOGTAG, "2nd Prediction : " + predictions.get(1).name);
-                    Log.v(LOGTAG, "3rd Prediction : " + predictions.get(2).name);
+                    Log.v(LOG_TAG, "1st Prediction : " + predictions.get(0).name +
+                            " @" + predictions.get(0).score);
+                    Log.v(LOG_TAG, "2nd Prediction : " + predictions.get(1).name +
+                            " @" + predictions.get(1).score);
+                    Log.v(LOG_TAG, "3rd Prediction : " + predictions.get(2).name +
+                            " @" + predictions.get(2).score);
                     int index = mContactAdapter.search(predictions.get(0).name);
                     if (index != -1) {
                         mContactList.setSelection(index);
@@ -112,9 +103,5 @@
                 }
             }
         });
-        overlay.addGestureListener(mGestureProcessor);
-        ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(
-                ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT);
-        this.addContentView(overlay, params);
     }
 }
diff --git a/tests/sketch/src/com/android/gesture/example/GestureEntry.java b/tests/sketch/src/com/android/gesture/example/GestureEntry.java
index 03a26da..3f86ed4 100644
--- a/tests/sketch/src/com/android/gesture/example/GestureEntry.java
+++ b/tests/sketch/src/com/android/gesture/example/GestureEntry.java
@@ -34,12 +34,11 @@
 import android.widget.EditText;
 import android.widget.Spinner;
 import android.widget.AdapterView.OnItemSelectedListener;
+import android.gesture.Gesture;
 
-import com.android.gesture.Gesture;
-import com.android.gesture.GestureLibrary;
-import com.android.gesture.GestureListener;
-import com.android.gesture.GestureOverlay;
-import com.android.gesture.Prediction;
+import android.gesture.GestureLibrary;
+import android.gesture.GestureOverlayView;
+import android.gesture.Prediction;
 
 import java.io.File;
 import java.util.ArrayList;
@@ -48,8 +47,9 @@
 
     private static final String PARCEL_KEY = "gesture";
 
-    static final String GESTURE_FILE_NAME = Environment.getExternalStorageDirectory().getAbsolutePath()
-            + File.separator + "gestureEntry.xml";
+    static final String GESTURE_FILE_NAME =
+            Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator +
+                    "demo_library.gestures";
 
     private static final int DIALOG_NEW_ENTRY = 1;
 
@@ -57,7 +57,7 @@
 
     private static final int VIEW_ID = Menu.FIRST + 1;
 
-    private GestureOverlay mGesturePad;
+    private GestureOverlayView mGesturePad;
 
     private Spinner mRecognitionResult;
 
@@ -83,7 +83,7 @@
                 // correct the recognition result by adding the new example
                 if (!mChangedByRecognizer) {
                     mGestureLibrary.addGesture(parent.getSelectedItem().toString(), mGesturePad
-                            .getCurrentGesture());
+                            .getGesture());
                 } else {
                     mChangedByRecognizer = false;
                 }
@@ -96,25 +96,28 @@
         });
 
         // create the area for drawing a gesture
-        mGesturePad = (GestureOverlay) findViewById(R.id.drawingpad);
+        mGesturePad = (GestureOverlayView) findViewById(R.id.drawingpad);
         mGesturePad.setBackgroundColor(Color.BLACK);
-        mGesturePad.addGestureListener(new GestureListener() {
-            public void onFinishGesture(GestureOverlay overlay, MotionEvent event) {
-                recognize(overlay.getCurrentGesture());
+        mGesturePad.addOnGestureListener(new GestureOverlayView.OnGestureListener() {
+            public void onGestureEnded(GestureOverlayView overlay, MotionEvent event) {
+                recognize(overlay.getGesture());
             }
 
-            public void onGesture(GestureOverlay overlay, MotionEvent event) {
+            public void onGesture(GestureOverlayView overlay, MotionEvent event) {
             }
 
-            public void onStartGesture(GestureOverlay overlay, MotionEvent event) {
+            public void onGestureStarted(GestureOverlayView overlay, MotionEvent event) {
                 overlay.clear(false);
             }
+            
+            public void onGestureCancelled(GestureOverlayView overlay, MotionEvent event) {
+            }
         });
 
         if (savedInstanceState != null) {
             Gesture gesture = (Gesture) savedInstanceState.getParcelable(PARCEL_KEY);
             if (gesture != null) {
-                mGesturePad.setCurrentGesture(gesture);
+                mGesturePad.setGesture(gesture);
             }
         }
     }
@@ -131,7 +134,7 @@
                                 .findViewById(R.id.gesturename_edit);
                         String text = edittext.getText().toString().trim();
                         if (text.length() > 0) {
-                            mGestureLibrary.addGesture(text, mGesturePad.getCurrentGesture());
+                            mGestureLibrary.addGesture(text, mGesturePad.getGesture());
                         }
                     }
                 }).setNegativeButton(R.string.newgesture_dialog_cancel,
@@ -155,7 +158,7 @@
     public boolean onOptionsItemSelected(MenuItem item) {
         switch (item.getItemId()) {
             case NEW_ID:
-                if (mGesturePad.getCurrentGesture() != null) {
+                if (mGesturePad.getGesture() != null) {
                     showDialog(DIALOG_NEW_ENTRY);
                 }
                 break;
@@ -188,7 +191,7 @@
     @Override
     protected void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
-        Gesture gesture = mGesturePad.getCurrentGesture();
+        Gesture gesture = mGesturePad.getGesture();
         if (gesture != null) {
             outState.putParcelable(PARCEL_KEY, gesture);
         }
diff --git a/tests/sketch/src/com/android/gesture/example/GestureLibViewer.java b/tests/sketch/src/com/android/gesture/example/GestureLibViewer.java
index ca54110..a561c96 100755
--- a/tests/sketch/src/com/android/gesture/example/GestureLibViewer.java
+++ b/tests/sketch/src/com/android/gesture/example/GestureLibViewer.java
@@ -26,10 +26,10 @@
 import android.widget.Button;
 import android.widget.Spinner;
 import android.widget.AdapterView.OnItemSelectedListener;
+import android.gesture.Gesture;
 
-import com.android.gesture.Gesture;
-import com.android.gesture.GestureLibrary;
-import com.android.gesture.GestureOverlay;
+import android.gesture.GestureLibrary;
+import android.gesture.GestureOverlayView;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -41,7 +41,7 @@
 
 public class GestureLibViewer extends Activity {
 
-    private GestureOverlay mGesturePad;
+    private GestureOverlayView mGesturePad;
 
     private Spinner mGestureCategory;
 
@@ -78,7 +78,7 @@
                     mCurrentGestureIndex--;
                 }
                 gesture = mGestures.get(mCurrentGestureIndex);
-                mGesturePad.setCurrentGesture(gesture);
+                mGesturePad.setGesture(gesture);
                 mGesturePad.invalidate();
             }
         }
@@ -90,7 +90,7 @@
         setContentView(R.layout.gestureviewer);
 
         // create the area for drawing a gesture
-        mGesturePad = (GestureOverlay) findViewById(R.id.drawingpad);
+        mGesturePad = (GestureOverlayView) findViewById(R.id.drawingpad);
         mGesturePad.setEnabled(false);
 
         // init the gesture library
@@ -109,7 +109,7 @@
             mGestures = mGesureLibrary.getGestures(list.get(0));
             mCurrentGestureIndex = 0;
             Gesture gesture = mGestures.get(mCurrentGestureIndex);
-            mGesturePad.setCurrentGesture(gesture);
+            mGesturePad.setGesture(gesture);
         }
 
         mGestureCategory.setOnItemSelectedListener(new OnItemSelectedListener() {
@@ -118,7 +118,7 @@
                 if (!mGestures.isEmpty()) {
                     mCurrentGestureIndex = 0;
                     Gesture gesture = mGestures.get(mCurrentGestureIndex);
-                    mGesturePad.setCurrentGesture(gesture);
+                    mGesturePad.setGesture(gesture);
                 }
                 mGesturePad.invalidate();
             }
@@ -139,7 +139,7 @@
                 }
                 mCurrentGestureIndex++;
                 Gesture gesture = mGestures.get(mCurrentGestureIndex);
-                mGesturePad.setCurrentGesture(gesture);
+                mGesturePad.setGesture(gesture);
                 mGesturePad.invalidate();
             }
         });
@@ -150,7 +150,7 @@
                 if (mCurrentGestureIndex >= 1 && !mGestures.isEmpty()) {
                     mCurrentGestureIndex--;
                     Gesture gesture = mGestures.get(mCurrentGestureIndex);
-                    mGesturePad.setCurrentGesture(gesture);
+                    mGesturePad.setGesture(gesture);
                     mGesturePad.invalidate();
                 }
             }
diff --git a/tests/sketch/tools/Converter.java b/tests/sketch/tools/Converter.java
index b4654f8..5db2769 100644
--- a/tests/sketch/tools/Converter.java
+++ b/tests/sketch/tools/Converter.java
@@ -15,6 +15,7 @@
  */
 public class Converter {
     private final File mFile;
+    private static final short VERSION_NUMBER = 1;
 
     Converter(File file) {
         mFile = file;
@@ -63,10 +64,10 @@
 
             iWeights = new float[hCount][];
             for (int i = 0; i < hCount; i++) {
-                iWeights[i] = new float[iCount];
+                iWeights[i] = new float[iCount + 1];
                 line = reader.readLine();
                 startIndex = 0;
-                for (int j = 0; j < iCount; j++) {
+                for (int j = 0; j <= iCount; j++) {
                     endIndex = line.indexOf(" ", startIndex);
                     iWeights[i][j] = Float.parseFloat(line.substring(startIndex, endIndex));
                     startIndex = endIndex + 1;
@@ -75,10 +76,10 @@
 
             oWeights = new float[oCount][];
             for (int i = 0; i < oCount; i++) {
-                oWeights[i] = new float[hCount];
+                oWeights[i] = new float[hCount + 1];
                 line = reader.readLine();
                 startIndex = 0;
-                for (int j = 0; j < hCount; j++) {
+                for (int j = 0; j <= hCount; j++) {
                     endIndex = line.indexOf(" ", startIndex);
                     oWeights[i][j] = Float.parseFloat(line.substring(startIndex, endIndex));
                     startIndex = endIndex + 1;
@@ -105,6 +106,7 @@
             try {
                 out = new DataOutputStream(new FileOutputStream(mFile));
 
+                out.writeShort(VERSION_NUMBER);
                 out.writeInt(iCount);
                 out.writeInt(hCount);
                 out.writeInt(oCount);
@@ -144,6 +146,7 @@
 
                     long start = System.nanoTime();
 
+                    in.readShort();
                     iCount = in.readInt();
                     hCount = in.readInt();
                     oCount = in.readInt();
diff --git a/tts/java/android/tts/ITts.aidl b/tts/java/android/tts/ITts.aidl
new file mode 100755
index 0000000..1fe4a6a
--- /dev/null
+++ b/tts/java/android/tts/ITts.aidl
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.tts;
+
+import android.tts.ITtsCallback;
+
+import android.content.Intent;
+
+/**
+ * AIDL for the TTS Service
+ * ITts.java is autogenerated from this.
+ *
+ * {@hide}
+ */
+interface ITts {
+    void setEngine(in String engineName, in String[] requestedLanguages, in int strictness);
+
+    void setEngineWithIntent(in Intent engineIntent);
+
+    void setSpeechRate(in int speechRate);
+
+    void speak(in String text, in int queueMode, in String[] params);
+
+    boolean isSpeaking();
+
+    void stop();
+
+    void addSpeech(in String text, in String packageName, in int resId);
+
+    void addSpeechFile(in String text, in String filename);
+
+    void setLanguage(in String language);
+
+    boolean synthesizeToFile(in String text, in String[] params, in String outputDirectory);
+
+    void playEarcon(in String earcon, in int queueMode, in String[] params);
+
+    void addEarcon(in String earcon, in String packageName, in int resId);
+
+    void addEarconFile(in String earcon, in String filename);
+
+    void registerCallback(ITtsCallback cb);
+
+    void unregisterCallback(ITtsCallback cb);
+}
diff --git a/tests/sketch/src/com/android/gesture/GestureActionListener.java b/tts/java/android/tts/ITtsCallback.aidl
old mode 100644
new mode 100755
similarity index 68%
rename from tests/sketch/src/com/android/gesture/GestureActionListener.java
rename to tts/java/android/tts/ITtsCallback.aidl
index c9c5232..1314010
--- a/tests/sketch/src/com/android/gesture/GestureActionListener.java
+++ b/tts/java/android/tts/ITtsCallback.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2009 The Android Open Source Project
+ * Copyright (C) 2009 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,8 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.gesture;
+package android.tts;
 
-public interface GestureActionListener {
-    public void onGesturePerformed(GestureOverlay overlay, Gesture gesture);
+/**
+ * AIDL for the callback from the TTS Service
+ * ITtsCallback.java is autogenerated from this.
+ *
+ * {@hide}
+ */
+oneway interface ITtsCallback {
+    void markReached(String mark);
 }
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 7c3af69..0db868e 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -58,7 +58,7 @@
 
     int getNumAllowedChannels();
 
-    boolean setNumAllowedChannels(int numChannels);
+    boolean setNumAllowedChannels(int numChannels, boolean persist);
 
     int[] getValidChannelCounts();
     
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 1a7caef..141d53f 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -538,14 +538,15 @@
      * for some reason.
      * @param numChannels the number of allowed channels. Must be greater than 0
      * and less than or equal to 16.
+     * @param persist {@code true} if you want this remembered
      * @return {@code true} if the operation succeeds, {@code false} otherwise, e.g.,
      * {@code numChannels} is out of range.
      *
      * @hide pending API council
      */
-    public boolean setNumAllowedChannels(int numChannels) {
+    public boolean setNumAllowedChannels(int numChannels, boolean persist) {
         try {
-            return mService.setNumAllowedChannels(numChannels);
+            return mService.setNumAllowedChannels(numChannels, persist);
         } catch (RemoteException e) {
             return false;
         }
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index 6771136..7ba124fd 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -183,6 +183,10 @@
     private boolean mUseStaticIp = false;
     private int mReconnectCount;
 
+    // used to store the (non-persisted) num determined during device boot 
+    // (from mcc or other phone info) before the driver is started.
+    private int mNumAllowedChannels = 0;
+
     // Variables relating to the 'available networks' notification
     
     /**
@@ -571,9 +575,12 @@
         try {
             return setNumAllowedChannels(
                     Settings.Secure.getInt(mContext.getContentResolver(),
-                                           Settings.Secure.WIFI_NUM_ALLOWED_CHANNELS));
+                    Settings.Secure.WIFI_NUM_ALLOWED_CHANNELS));
         } catch (Settings.SettingNotFoundException e) {
-            // if setting doesn't exist, stick with the driver default
+            if (mNumAllowedChannels != 0) {
+                WifiNative.setNumAllowedChannelsCommand(mNumAllowedChannels);
+            }
+            // otherwise, use the driver default
         }
         return true;
     }
@@ -587,6 +594,7 @@
      * {@code numChannels} is outside the valid range.
      */
     public synchronized boolean setNumAllowedChannels(int numChannels) {
+        mNumAllowedChannels = numChannels;
         return WifiNative.setNumAllowedChannelsCommand(numChannels);
     }